gpt4 book ai didi

r - 如何使用 dplyr 添加灵活的增量列?

转载 作者:行者123 更新时间:2023-12-04 12:11:44 24 4
gpt4 key购买 nike

我想使用 dplyr 向数据集添加“delta”列。增量将计算为当前行值与前一行值之间的差值。挑战在于前一行不一定是正确的,因为需要进行一些过滤。

考虑这个数据集:

LEVEL, TIME
3, 0000
2, 0010
2, 0020
1, 0030
2, 0040
3, 0050

我想添加一个新列 DELTA,其中包含 TIME 值与前一个 TIME 值之间的差异,对于具有相同 LEVEL 或更高级别的行。也就是说,我不想与紧接在前的行进行比较,而是想向后搜索并跳过任何级别较低的行。

对于这个例子,预期的输出是:

LEVEL, TIME, DELTA
3, 0000, NA
2, 0010, 10
2, 0020, 10
1, 0030, 10
2, 0040, 20
3, 0050, 50

这可以用 dplyr 直接完成吗? (否则?)

我想要一个高效的解决方案,因为我的真实数据集大约有 10 亿行,并且有七个时间戳列(但只有一个级别。)

(背景:数据来自软件应用程序日志文件,使用了 CPU 提供的许多时间源,例如周期、指令和 L1/L2/L3/DRAM 访问计数器。我想测量事件之间耗时。较低级别的消息不是单独的先行事件,而是更细粒度的细节。)

使用新信息进行编辑:

我用 dplyr 尝试过的所有解决方案都无法真正适用于我的百万元素数据集。它们似乎很慢并且会破坏 R 过程。

我已经退回到学习一些基础 R 并编写一个相当实用的(1M 行数据帧大约 2 秒)实现,如下所示:

level <- c(3,2,2,1,2,3,6,4,7,8,2) # recycled to 1M elements, below
time <- seq(0, 10000000, 10)

# reference timestamp accumulator for update inside closure.
# index is log level and value is reference timestamp for delta.
ref <- numeric(9)
f <- function(level, time) {
delta <- time - ref[level]
ref[1:level] <<- time
delta
}

delta <- mapply(f, level, time)

这合理吗?是否有类似的 dplyr 解决方案?

基本满意。我确实觉得这应该快 10 倍,每个向量元素 ~5000 个 CPU 周期似乎有点疯狂,但它对我有用,并且在复制 ref 的解释器的上下文中可能是合理的每一步的累加器。

EDIT2:经过反射(reflection),这个公式的性能有点拖后腿。如果可能,我想要 10 倍的加速!

最佳答案

我加入了 data.frame 本身。然后选择符合您条件的所有行。然后选择最接近的匹配行。为了在结果中获得相同数量的行(第一行中的 NA),我再次加入基本 data.frame (right_join)。

LEVEL <- c(3,2,2,1,2,3)
TIME <- c('0000','0010','0020','0030','0040','0050')

df <- data.frame(LEVEL, TIME, stringsAsFactors = F)

df %>%
merge(df, by = NULL, all=T) %>%
filter(LEVEL.y >= LEVEL.x & TIME.x > TIME.y) %>%
group_by(TIME.x, LEVEL.x) %>%
filter(row_number(desc(TIME.y))==1) %>%
mutate(delta = as.numeric(TIME.x) - as.numeric(TIME.y)) %>%
rename(LEVEL = LEVEL.x, TIME=TIME.x) %>%
select(TIME, LEVEL, delta) %>%
right_join(df)

另一种方法是计算每个组的 min(delta),而不是排序和选择第一行。我更喜欢上面的解决方案,因为您还可以使用匹配行的其他信息。

df %>% merge(df, by = NULL, all=T) %>%  
filter(LEVEL.y >= LEVEL.x & TIME.x > TIME.y) %>%
group_by(TIME.x, LEVEL.x) %>%
summarise(delta = min(as.numeric(TIME.x) - as.numeric(TIME.y))) %>%
rename(LEVEL = LEVEL.x, TIME=TIME.x) %>%
select(TIME, LEVEL, delta) %>%
right_join(df)

关于r - 如何使用 dplyr 添加灵活的增量列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41934604/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com