我正在尝试将R中的函数应用于每一行,同时用上一行函数的输出更新每一行。我知道这是一大口,但这里有一个例子。假设我有dataframe,df:
df<- data.frame(a=c(10,15,20,25,30), b=c(2,4,5,7,10))
我有一个函数,funR,它取了列a和列b之间的区别:
funR<- function(argA, argB){
c<- argA-argB
return(c)
}
现在,我要做的一个简化版本是,我将函数应用到第一行,得到10-2= 8。然后,在将函数应用到该行之前,我希望用这个输出替换第二列a,所以我将执行8-4,然后用4替换第3行中的20,以此类推。
编辑以显示预期输出:
a b
1 10 2
2 8 4
3 4 5
4 -1 7
5 -8 10
任何帮助都将不胜感激!
发布于 2018-03-10 15:37:08
这确实是R基的一个单线线:
方法1:
for (i in 1:(nrow(df) - 1)) df$a[i + 1] <- df$a[i] - df$b[i];
df;
# a b
#1 10 2
#2 8 4
#3 4 5
#4 -1 7
#5 -8 10
在这里,我们实现了递归关系a[i+1] = a[i] - b[i]
在一个简单的for
循环。for
循环将非常快,因为我们直接覆盖df
中的现有条目。
方法2
或者另一种选择:
df$a <- df$a[1] - cumsum(c(0, df$b))[1:length(df$a)];
df;
# a b
#1 10 2
#2 8 4
#3 4 5
#4 -1 7
#5 -8 10
这是基于扩展的递归关系,您可以看到,例如,a[4] = a[1] - (b[1] + b[2] + b[3])
,等等。
发布于 2018-03-10 15:44:43
如果您想维护函数funR
的使用,这里有一个更快的版本。
df<- data.frame(a=c(10,15,20,25,30), b=c(2,4,5,7,10))
funR<- function(argA, argB){
n = length(argA)
argC = c(argA[1], argB)
accumdiff <- function(x){
Reduce(function(x1,x2) x1-x2, x, accumulate=TRUE)}
argC = c(argA[1],accumdiff(argC)[c(-1)])
rev(rev(argC)[-1])
}
df$a <- funR(df$a, df$b)
df
# a b
# 1 10 2
# 2 8 4
# 3 4 5
# 4 -1 7
# 5 -8 10
发布于 2018-03-10 15:52:57
我们也可以使用来自accumulate
的purrr
来实现这一点。
library(purrr)
library(dplyr)
df %>%
mutate(a = accumulate(b[-n()], `-`, .init = a[1]))
# a b
#1 10 2
#2 8 4
#3 4 5
#4 -1 7
#5 -8 10
https://stackoverflow.com/questions/49210683
复制相似问题