如何在数据帧的每一列中有效地将继任者按前任划分

How to efficiently divide successor by predecessor in each column of a dataframe

我有一个 dataframe myDF 是这样创建的:

a <- 1:4
b <- seq(3, 16, length=4)
myDF <- data.frame(a=a, b=b)

看起来像这样:

  a         b
1 1  3.000000
2 2  7.333333
3 3 11.666667
4 4 16.000000

现在我想在每一列中划分后续的前驱和后继,将结果添加到现有数据框中,用 NA 替换每列中的一个缺失值并添加新的列名。对于上面的例子,我想要的结果是这样的:

  a         b     amod     bmod
1 1  3.000000       NA       NA
2 2  7.333333 2.000000 2.444444
3 3 11.666667 1.500000 1.590909
4 4 16.000000 1.333333 1.371429

因此,在 a 列中,2 除以 1,3 除以 2,4 除以 3,结果存储在 amod.

我现在的做法是这样的:

divStuff <-function(aCol){

  newCol <- aCol[2:length(aCol)]/aCol[1:length(aCol) - 1]
  newCol <- c(NA, newCol)

  return(newCol)
}
newDF <- data.frame(lapply(myDF, divStuff))
names(newDF) <- paste(names(myDF), "mod", sep="")
endDF <- cbind(myDF, newDF)

我编写了一个函数 divStuff 进行除法,然后调用 lapply 将此函数应用于数据框的每一列。

现在我想知道这是否是执行此操作的方法,或者是否有更聪明的方法来执行此类操作,例如避免 cbind 调用或以一种通过自动添加 NA 来避免行 newCol <- c(NA, newCol) 的方式执行 cbind。我没有找到好的方法,所有解决方案看起来都类似于 this one

这是一个快速 data.table 版本(使用 devel version on GH

library(data.table) ## V 1.9.5
setDT(myDF)[, paste0(names(myDF), "mod") := lapply(.SD, function(x) x/shift(x))]
#    a         b     amod     bmod
# 1: 1  3.000000       NA       NA
# 2: 2  7.333333 2.000000 2.444444
# 3: 3 11.666667 1.500000 1.590909
# 4: 4 16.000000 1.333333 1.371429

或者与 dplyr 类似,尽管您可能想尝试使用列名(这是由于 mutate_each 中的错误(?),当它删除原始列并且不重命名时给定单个函数时的结果)

library(dplyr)
myDF %>% 
  mutate_each(funs(./lag(.))) %>%
  cbind(myDF, .)
#   a         b        a        b
# 1 1  3.000000       NA       NA
# 2 2  7.333333 2.000000 2.444444
# 3 3 11.666667 1.500000 1.590909
# 4 4 16.000000 1.333333 1.371429

base R:

myDF[,paste0(names(myDF), "mod")] <- sapply(myDF, function(x) c(NA, x[-1]/head(x,-1)))
#  a         b     amod     bmod
#1 1  3.000000       NA       NA
#2 2  7.333333 2.000000 2.444444
#3 3 11.666667 1.500000 1.590909
#4 4 16.000000 1.333333 1.371429