zeus
zeus

Reputation: 9

calculate the percentage change of every nth row in the dataframe

I am trying to calculate the percent change in the values of the dataframe. Now the rows for which the percent change has to be calculated is entered by the user. If the user enters 2 then for every 2nd row the percentage change will be calculated. I have the following function:

change <- function(DF, change) {
   numCols <- ncol(DF)
    for (i in 1: numCols) {
      pctChange <-rep(NA,nrow(DF))
        x<-DF[,i]
        y<-c(DF[(change+1):nrow(DF),i], rep(NA,change))
        pctChange <-round((y-x)*100/x,2)
        DF$pct<-pctChange
        colnames(DF)[ncol(DF)]<-paste(colnames(DF[i]),"pctChangeby",
                                                    change,sep = "")
      }
      return (DF)
    }

When i tested this function:

change(mtcars[1:5], 1)

I got the following output: (just showing output for first row:

                   mpg       mpgpctChangeby1
Mazda RX4           22.8            7.02
Mazda RX4 Wag       24.4            -6.56
Datsun 710          22.8           42.11
Hornet 4 Drive      32.4            -6.17

Expected Output:

                 mpg       mpgpctChangeby1
Mazda RX4           22.8            NA
Mazda RX4 Wag       24.4           7.02
Datsun 710          22.8           -6.56
Hornet 4 Drive      32.4            42.11

For change = 2,

Expected Output:

                    mpg       mpgpctChangeby2
Mazda RX4           21.0            NA
Mazda RX4 Wag       21.0            NA
Datsun 710          22.8            8.57
Hornet 4 Drive      21.4            1.90
Hornet Sportabout   18.7          -17.98

Upvotes: 0

Views: 423

Answers (1)

akrun
akrun

Reputation: 887158

By running your function change, I am getting a different output than the one you showed.

  change(mtcars[1],1)[1:4,]
 #               mpg mpgpctChangeby1
 #Mazda RX4      21.0            0.00
 #Mazda RX4 Wag  21.0            8.57
 #Datsun 710     22.8           -6.14
 #Hornet 4 Drive 21.4          -12.62

I guess this would help in getting your expected output:

For change=2

  mtcars1 <- mtcars[,1] #1 column
  x <- c(rep(NA,2), mtcars1[-((length(mtcars1)-1):length(mtcars1))])
  y <- c(rep(NA,2), mtcars1[-(1:2)])
    round(100*(y-x)/x,2)
  # [1]     NA     NA   8.57   1.90 -17.98 -15.42 -23.53  34.81  59.44 -21.31
 #[11] -21.93 -14.58  -2.81  -7.32 -39.88 -31.58  41.35 211.54 106.80   4.63
 #[21] -29.28 -54.28 -29.30 -14.19  26.32 105.26  35.42  11.36 -39.23 -35.20
 #[31]  -5.06   8.63

For change=3

 x <- c(rep(NA,3), mtcars1[-((length(mtcars1)-2):length(mtcars1))])
 y <- c(rep(NA,3), mtcars1[-(1:3)])
 round(100*(y-x)/x,2)
 # [1]     NA     NA     NA   1.90 -10.95 -20.61 -33.18  30.48  25.97  34.27
 #[11] -27.05 -28.07  -9.90 -14.61 -36.59 -39.88  -3.29 211.54 192.31 130.61
 #[21] -33.64 -49.01 -55.16 -38.14  23.87  79.61  95.49  58.33 -42.12 -24.23
 #[31] -50.66  35.44

Regarding the change=1, the values you showed for mpg are not matching with the rownames. By changing your function:

 change <- function(DF, change) {
 numCols <- ncol(DF)
 for (i in 1: numCols) {
  pctChange <-rep(NA,nrow(DF))
    x<- c(rep(NA, change), DF[-((nrow(DF)-(change-1)):nrow(DF)),i])
    y<-c(rep(NA, change), DF[-(seq_len(change)),i])
    pctChange <-round((y-x)*100/x,2)
    DF$pct<-pctChange
    colnames(DF)[ncol(DF)]<-paste(colnames(DF[i]),"pctChangeby",
                                                change,sep = "")
  }
  return (DF)
}

 change(mtcars[1],2)[1:6,]
#                   mpg mpgpctChangeby2
#Mazda RX4         21.0              NA
#Mazda RX4 Wag     21.0              NA
#Datsun 710        22.8            8.57
#Hornet 4 Drive    21.4            1.90
#Hornet Sportabout 18.7          -17.98
#Valiant           18.1          -15.42

change(mtcars[1],3)[1:6,]
change(mtcars[1],1)[1:6,]

Upvotes: 1

Related Questions