【问题标题】:Vectorizing or for loop or apply function?矢量化或for循环或应用函数?
【发布时间】:2015-01-30 06:52:40
【问题描述】:

我有一个包含 6 列的数据框。第 1 列保存日期,第 2 列个人和第 3 到 6 列用于计算。

Date <- c(1, 1, 2, 2, 2, 3)
Ind <- c("a","a","a","b","c","c")
C <- c(5, 6, 5, 7, 8, 8)
D <- c(8, 8, 9, 9, 9, 9)
E <- c(8, 9, 11, 10, 9, 7)
F <- c(5, 6, 8, 5, 7, 4)

df <- data.frame(Date, Ind, C, D, E, F)

我想执行一个计算(例如 (C-E)+(D-F) (在现实生活中,这些是坐标,我正在计算距离,但这不是我现在的问题所在)。

我想执行计算,存储在一个新列 (G) 中,我使用第 1 天的 C 和 E 列的值与第 1 天的 E 和 F 列的值之间存在 1 天的差异1 为同一个人。

我不确定我应该使用循环还是应用函数。这是我迄今为止尝试过的,基于此线程的矢量化操作和子集:Loop over rows of dataframe applying function with if-statement

df$G <- NA

df[!(df$Date ==(df$Date+1)), "G"] <- ((C-E)+(D-F))

这可行,但它对同一行的坐标进行计算(C、D、E、F 都来自同一行)。我意识到它为什么这样做,因为我没有说明从哪一行获取坐标。 C 和 D 需要取自 Date = Date 的行,E 和 F 取自 Date = (Date+1) 的行。 我意识到这一点,但我不知道该怎么做。

继续这条路线?在for循环中做吗?使用应用功能?

【问题讨论】:

  • Ind a 有两行日期 1。你想做什么?
  • 距离通常为 L1:abs(C-D)+ abs(E-F) 或 L2:(C-D)^2 + (E-F)^2,即始终为正。
  • @egilio 你的描述有点混乱。您能否显示此示例数据的预期输出。

标签: r


【解决方案1】:

dplyr 包提供了非常好的laglead 函数。

> library(dplyr)
> df %>% mutate(G = C + D + lead(E,1) + lead(F,1))
  Date Ind C D  E F  G
1    1   a 5 8  8 5 28
2    1   a 6 8  9 6 33
3    2   a 5 9 11 8 29
4    2   b 7 9 10 5 32
5    2   c 8 9  9 7 28
6    3   c 8 9  7 4 NA

最后一行的 G 是 NA,因为没有 next 日期值。

编辑:

正如其他人所提到的,您的示例数据看起来有两个日期为Ind==a。在这种情况下,您可能要小心领先/落后。

如果这样做有意义,您可以先聚合它们,然后再进行领先/滞后。

df %>% group_by(Date,Ind) %>% 
  summarise(C=mean(C),D=mean(D),E=mean(E),F=mean(F)) %>%
  ungroup %>%
  mutate(G = C + D + lead(E,1) + lead(F,1))

产生:

  Date Ind   C D    E   F    G
1    1   a 5.5 8  8.5 5.5 32.5
2    2   a 5.0 9 11.0 8.0 29.0
3    2   b 7.0 9 10.0 5.0 32.0
4    2   c 8.0 9  9.0 7.0 28.0
5    3   c 8.0 9  7.0 4.0   NA

【讨论】:

  • Date 列与 3:51:2 行相同。此外,它似乎按Ind 分组。所以,我不确定这是否正确。
  • 感谢您指出这一点。我假设这不是数据的预期功能,因为 OP 没有提到如何处理。
  • 我正在查看 OP 的代码 df$Date ==(df$Date+1)。也许你是对的,但示例和描述令人困惑。
猜你喜欢
  • 2015-05-17
  • 1970-01-01
  • 2014-09-25
  • 1970-01-01
  • 1970-01-01
  • 2017-07-22
  • 2019-06-14
  • 2020-05-03
相关资源
最近更新 更多