[R data.frame根据行值增加一列
在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)
这是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
可以使用lag功能的实现是这样的:
myFrame$SumX[1] <- X[1]
myFrame$SumX[2:nrow(myFrame)] <- X[2:nrow(myFrame)]+lag(X)[2:nrow(myFrame)]
这也运行得相当不错。谢谢! – BlainTheMono
#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
从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
。
非常感谢!这工作得很好。我不得不承认,我有更多的操作要做,而不仅仅是总结2个值。(dfSomeFrame,SumX = abs((dfSomeFrame $ X - lag(dfSomeFrame $ X,default = 0)))^ 2) dfSomeFrame $ SumX [1] BlainTheMono
这样'mutate'的结果被写回到我的data.frame中,所以可以用Y做更多的操作,甚至可以构建一个新的SUMZ和SumY列。 (不知何故'lag(..)'中的'default = 0'不起作用,所以我不得不使用'dfSomeFrame $ SumX [1] BlainTheMono
太棒了!很少有事情需要修改:在mutate()中,你不需要重用'dfSomeFrame $'。相反,尝试'dfSomeFrame