【问题标题】:apply function for iterating over dataframe and generating columns based on index column用于迭代数据帧并基于索引列生成列的应用函数
【发布时间】:2020-03-01 19:02:56
【问题描述】:

让我来描述一下数据:

  • abcxyz 是指标。
  • hit 基本上是索引号,例如:
    • 命中值3表示abc3和xyz3中对应的值
    • hit 4 表示 abc4, xyz4

数据

dat <- data.frame( abc1=c(7, 0, 7), 
                   abc2=c(5, 10, 20), 
                   abc3=c(0, 0, 10), 
                   abc4=c(3, 5, 19), 
                   abc5=c(2, 2, 0), 
                   abc6=c(2, 26, 0),
                   xyz1=c(0, 2, 0),
                   xyz2=c(1, 1, 6),
                   xyz3=c(8, 2, 0),
                   xyz4=c(6, 3, 5),
                   xyz5=c(9, 2, 2),
                   xyz6=c(4, 0, 0),
                   hit=c(3, 4, 4))

我需要做的是找到命中前和命中后的 abc 和 xyz。 下面的 for 循环可以很好地处理小型数据集,但如果数据超过 100k 行,则循环似乎永远运行。

for (c in c('abc','xyz')){
  for (i in 1:nrow(dat)){
    for (m in -2:2){

      dat[[paste(c,'hit', m)]][i] = dat[i,paste(c, dat$hit[i]-m, sep = "")]
    }
  }
}

在输出文件中, 第 1 行的 'abc hit 0' 指的是:hit=3,它依次选择 abc3 中的值并分配给 abc hit 0

abc hit -1 转换为 hit=3-1=2 指向 abc2xyz2

我知道 3 个 for 循环是个坏主意。请通过使用应用函数或任何其他减少执行时间的方式帮助我改进代码。

【问题讨论】:

  • 如果您的数据长度(即一个 abc 和一个 xyz 列)不宽且带有后缀列,那么您的过程会容易得多。 Long 可以说是促进聚合、合并、绘图、建模等数据科学的首选格式。

标签: r dataframe for-loop optimization apply


【解决方案1】:

您似乎在 for 循环中颠倒了“m”:它从 -2 运行到 2,但随后您得到了 dat$hit - m - 减法是您想要的吗?还是应该是dat$hit + m

您可以执行以下操作 - 我尚未在大型数据集上对其进行测试,但请试一试:

dat1 <- do.call(rbind, 
                lapply(split(dat, 1:NROW(dat)), 
                       function(x) {
                          z <- x[paste0('abc', x$hit + 2:-2)]; 
                          names(z) <- paste0('abc', -2:2); 
                          z 
                       }
                ))

split 函数为您提供数据框的行,愉快地保留列名,然后您可以使用lapply 函数逐行操作。

您可以通过将 -2 到 2 添加到 hit 来查找每行的相关列。

然后你将生成的列表重新组合成一个数据框。

更新: 对于 90K 行,这比上述速度快 30%:

dat1 <- t(sapply(split(dat, 1:NROW(dat)), 
                       function(x) unname(x[paste0('abc', x$hit + 2:-2)])  
                ))
dat1 <- as.data.frame(dat1)
colnames(dat1) <- paste0('abc', -2:2)

【讨论】:

  • 感谢您的回答,我会检查一下。是的,数据帧的性质是,对于 m,循环应该以相反的顺序运行。
猜你喜欢
  • 1970-01-01
  • 2016-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-07
相关资源
最近更新 更多