2017-02-23 186 views
1

在R,我有data.frame,看起来像这样:[R data.frame根据行值增加一列

X Y 
20 7 
25 84 
15 62 
22 12 
60 24 
40 10 
60 60 
12 50 
11 17 
现在

,我希望有一个新的科拉姆,让我们把它叫做“SUMX” ,将X的两个以下值添加到SumX列的新字段中,并将相同的值添加到“SumY”列。所以结果data.frame是这样的:

X Y SumX     SumY 
20 7 20 #first row = X 7 #first row = Y 
25 84 45 #X0 + X1  91 #Y0 + Y1 
15 62 40 #X1 + X2  146 #Y1 + Y2 
22 12 37 #X2 + X3  74 #Y2 + Y3 
60 24 82 #X3 + X4  36 #Y3 + Y4 
40 10 100 #X4 + X5  34 #Y4 + Y5 
60 60 100 #and so on  70 #and so on 
12 50 72     110 
11 17 23     67 

我可以做简单的X + Y到一个新列

myFrame$SumXY <- with(myFrame, X+Y) 

,但它有一个简单的方法来添加两个X(N + (n-1))值转换为SumX,将两个Y(n +(n-1))转换为SumY?即使它是一个while循环,尽管我更喜欢更简单的方式(它有很多像这样的数据)。任何帮助深表感谢! (我还是很新的R)

回答

2

这是dplyr方法。

使用mutate()添加一个新的colum和​​来计算您的变量。例如:

library(dplyr) 

d <- data.frame(
    x = 1:10, 
    y = 11:20, 
    z = 21:30 
) 

mutate(d, sumx = x + lag(x, default = 0)) 

#>  x y z sumx 
#> 1 1 11 21 1 
#> 2 2 12 22 3 
#> 3 3 13 23 5 
#> 4 4 14 24 7 
#> 5 5 15 25 9 
#> 6 6 16 26 11 
#> 7 7 17 27 13 
#> 8 8 18 28 15 
#> 9 9 19 29 17 
#> 10 10 20 30 19 

以上的变量可以类似地处理:

mutate(d, sumx = x + lag(x, default = 0), sumy = y + lag(y, default = 0)) 
#>  x y z sumx sumy 
#> 1 1 11 21 1 11 
#> 2 2 12 22 3 23 
#> 3 3 13 23 5 25 
#> 4 4 14 24 7 27 
#> 5 5 15 25 9 29 
#> 6 6 16 26 11 31 
#> 7 7 17 27 13 33 
#> 8 8 18 28 15 35 
#> 9 9 19 29 17 37 
#> 10 10 20 30 19 39 

如果您知道您要为多,或在您的数据帧,甚至每一列这样做,那么这里有一个标准的评价方法与mutate_()使用自定义函数我改编自this blog post(注意您需要安装lazyeval包)。该函数被应用于for循环中的每一列(可能会被优化)。

f <- function(df, col, new_col_name) { 
    mutate_call <- lazyeval::interp(~ x + lag(x, default = 0), x = as.name(col)) 
    df %>% mutate_(.dots = setNames(list(mutate_call), new_col_name)) 
} 

for (var in names(d)) { 
    d <- f(d, var, paste0('sum', var)) 
} 

d 
#>  x y z sumx sumy sumz 
#> 1 1 11 21 1 11 21 
#> 2 2 12 22 3 23 43 
#> 3 3 13 23 5 25 45 
#> 4 4 14 24 7 27 47 
#> 5 5 15 25 9 29 49 
#> 6 6 16 26 11 31 51 
#> 7 7 17 27 13 33 53 
#> 8 8 18 28 15 35 55 
#> 9 9 19 29 17 37 57 
#> 10 10 20 30 19 39 59 

只是继续tidyverse主题,下面是一个使用purrr封装解决方案(同样适用于所有列,但子集列,如果需要):

library(purrr) 

# Create new columns in new data frame. 
# Subset `d` here if only want select columns 
sum_d <- map_df(d, ~ . + lag(., default = 0)) 

# Set names correctly and 
# bind back to original data 
names(sum_d) <- paste0("sum", names(sum_d)) 
d <- cbind(d, sum_d) 
d 
#>  x y z sumx sumy sumz 
#> 1 1 11 21 2 22 42 
#> 2 2 12 22 4 24 44 
#> 3 3 13 23 6 26 46 
#> 4 4 14 24 8 28 48 
#> 5 5 15 25 10 30 50 
#> 6 6 16 26 12 32 52 
#> 7 7 17 27 14 34 54 
#> 8 8 18 28 16 36 56 
#> 9 9 19 29 18 38 58 
#> 10 10 20 30 20 40 60 
+0

非常感谢!这工作得很好。我不得不承认,我有更多的操作要做,而不仅仅是总结2个值。(dfSomeFrame,SumX = abs((dfSomeFrame $ X - lag(dfSomeFrame $ X,default = 0)))^ 2) dfSomeFrame $ SumX [1] < - 0' – BlainTheMono

+0

这样'mutate'的结果被写回到我的data.frame中,所以可以用Y做更多的操作,甚至可以构建一个新的SUMZ和SumY列。 (不知何故'lag(..)'中的'default = 0'不起作用,所以我不得不使用'dfSomeFrame $ SumX [1] < - 0')。再次感谢 – BlainTheMono

+0

太棒了!很少有事情需要修改:在mutate()中,你不需要重用'dfSomeFrame $'。相反,尝试'dfSomeFrame < - mutate(dfSomeFrame,SumX = abs((X-lag(X,default = 0)))^ 2)'。 –

1

可以使用lag功能的实现是这样的:

myFrame$SumX[1] <- X[1] 
myFrame$SumX[2:nrow(myFrame)] <- X[2:nrow(myFrame)]+lag(X)[2:nrow(myFrame)] 
+0

这也运行得相当不错。谢谢! – BlainTheMono

1
#SumX 
cumsum(df$X) - c(0, 0, cumsum(df$X)[1:(nrow(df)-2)]) 
#[1] 20 45 40 37 82 100 100 72 23 

#SumY 
cumsum(df$Y) - c(0, 0, cumsum(df$Y)[1:(nrow(df)-2)]) 
#[1] 7 91 146 74 36 34 70 110 67 
3

zoo封装的rollapply功能将在这里工作。

以下代码块将创建每两个相邻值的滚动总和。

require(zoo) 
myFrame$SumX <- rollapply(myFrame$X, 2, sum) # this is a rolling sum of every 2 values 

你可以以不具有滚动总和添加by = 2作为参数传递给rollapply(即,它求和值1 + 2,然后3 + 4,然后5 + 6等)。

查阅更多信息?rollapply