r - 根据条件聚合 r

标签 r aggregate

我的数据集包含四列X1(ID号)、X2(日期时间)、X3(日期时间)、 X4(持续时间)如下

test2 = structure(list(X1 = c(549395L, 678018L, 706197L, 549395L, 775731L, 789858L, 845277L, 936749L, 845277L, 954953L), X2 = c("6/16/2014", "9/16/2014", "2/12/2014", "6/16/2014", "8/29/2014", "2/26/2014", "4/7/2014", "2/14/2014", "5/18/2014", "3/5/2014"), X3 = c("6/4/2014 11:10", "9/16/2014 10:23", "2/12/2014 12:21", "6/4/2014 11:10", "8/29/2014 8:51", "2/26/2014 12:49", "4/7/2014 13:59", "2/14/2014 12:08", "4/7/2014 01:39", "3/5/2014 10:14"), X4 = c(8L, 21L, 10L, 72L, 39L, 14L, 41L, 31L, 43L, 24L)), .Names = c("X1", "X2", "X3", "X4"), class = "data.frame", row.names = c(NA, -10L))

       X1        X2              X3 X4
1  549395 6/16/2014  6/4/2014 11:10  8
2  678018 9/16/2014 9/16/2014 10:23 21
3  706197 2/12/2014 2/12/2014 12:21 10
4  549395 6/16/2014  6/4/2014 11:10 72
5  775731 8/29/2014  8/29/2014 8:51 39
6  789858 2/26/2014 2/26/2014 12:49 14
7  845277  4/7/2014  4/7/2014 13:59 41
8  936749 2/14/2014 2/14/2014 12:08 31
9  845277 5/18/2014  4/7/2014 01:39 43
10 954953  3/5/2014  3/5/2014 10:14 24

我想要完成的是这个

  1. 如果 X1(ID 号)在 X3 中具有相同的日期和时间,则将其对应的 X4 替换为 其中 x4 的最大值。例如,身份证号码 (549395 ) 具有相同的日期和时间 (x3) 6/4/2014 11:10,因此 X4 应替换为 max(72, 8) ... 72.

  2. 如果X1(ID号码)具有相同的日期但不同的时间,则将其相应的X4替换为其各自的总和 x4s。例如,身份证号 (845277) 具有相同的日期 (4/7/2014) 不同的时间 (13:59, 1:39),因此 X4 应该是 sum (43,41) = 84

输出应如下所示。

       X1        X2              X3  X4
1  549395 6/16/2014  6/4/2014 11:10  72
2  678018 9/16/2014 9/16/2014 10:23  21
3  706197 2/12/2014 2/12/2014 12:21  10
4  549395 6/16/2014  6/4/2014 11:10  72
5  775731 8/29/2014 8/29/2014  8:51  39
6  789858 2/26/2014 2/26/2014 12:49  14
7  845277  4/7/2014  4/7/2014 13:59  84
8  936749 2/14/2014 2/14/2014 12:08  31
9  845277 5/18/2014  4/7/2014 01:39  84
10 954953  3/5/2014  3/5/2014 10:14  24

我尝试使用聚合函数,但结果与我想要完成的目标相差甚远。所以需要帮助。

新数据:

test2=   structure(list(X1 = c(1491930L, 3162932L, 3162932L, 4092879L, 
5374073L, 7427514L, 2377939L, 2377939L, 4081399L), X2 = structure(c(16073, 
16073, 16073, 16073, 16074, 16073, 16081, 16081, 16077), class = "Date"), 
X3 = structure(c(4L, 5L, 1L, 3L, 6L, 2L, 9L, 8L, 7L), .Label = c("2014-01-03 10:11", 
"2014-01-03 11:1", "2014-01-03 11:44", "2014-01-03 8:47", 
"2014-01-03 9:40", "2014-01-04 11:7", "2014-01-07 8:42", 
"2014-01-11 2:58", "2014-01-11 2:6"), class = "factor"), 
X4 = c(31, 26, 4, 32, 24, 132, 50, 16, 66)), .Names = c("X1", 
"X2", "X3", "X4"), row.names = c(NA, -9L), class = "data.frame")

期望的结果:

          X1         X2       date       time  X4
        1 1491930 2014-01-03 2014-01-03  8:47  31
        2 3162932 2014-01-03 2014-01-03  9:40  30
        3 3162932 2014-01-03 2014-01-03 10:11  30
        4 4092879 2014-01-03 2014-01-03 11:44  32
        5 5374073 2014-01-04 2014-01-04  11:7  24
        6 7427514 2014-01-03 2014-01-03  11:1 132
        7 2377939 2014-01-11 2014-01-11   2:6  66
        8 2377939 2014-01-11 2014-01-11  2:58  66
        9 4081399 2014-01-07 2014-01-07  8:42  66

最佳答案

这是一个如何使用 dplyr 和 tidyr 来完成此操作的选项。我添加了一些日期格式,这会增加“管道”的长度,但在我看来这是值得的。我会将管道的这些部分标记为“可选”。

library(dplyr); library(tidyr)

test2 %>%
  separate(X3, into = c("date", "time"), sep = " ") %>%
  mutate_each(funs(as.Date(., format = "%Y-%m-%d")), X2, date) %>%
  group_by(X1, date, time) %>%
  mutate(X4 = max(X4)) %>%
  group_by(X1, date) %>%
  mutate(X4 = ifelse(n_distinct(time) == 1L, X4, sum(X4))) %>%
  ungroup() %>%
  unite(X3, date:time, sep = " ") %>%
  mutate(X3 = as.POSIXct(X3))

使用数据集,会产生:

Source: local data frame [9 x 4]

       X1         X2                  X3  X4
1 1491930 2014-01-03 2014-01-03 08:47:00  31
2 3162932 2014-01-03 2014-01-03 09:40:00  30
3 3162932 2014-01-03 2014-01-03 10:11:00  30
4 4092879 2014-01-03 2014-01-03 11:44:00  32
5 5374073 2014-01-04 2014-01-04 11:07:00  24
6 7427514 2014-01-03 2014-01-03 11:01:00 132
7 2377939 2014-01-11 2014-01-11 02:06:00  66
8 2377939 2014-01-11 2014-01-11 02:58:00  66
9 4081399 2014-01-07 2014-01-07 08:42:00  66

我首先将原始 X3 列分成数据和时间两列(使用与 tidyr 分开的方式),并将 X2 列和日期格式化为真正的日期格式。接下来,我按 X1、日期和时间对数据进行分组,然后将 X4 替换为每个日期/时间组中的最大 X4。然后我仅按 X1 和日期对数据进行分组,并检查唯一时间值的数量是否为 1。如果是,则返回 X4 不变,否则返回 X4 的总和。接下来是取消数据分组,将日期和时间列合并回单个列 X3,并使用 as.POSIXct 将 X3 格式化为日期时间。


有一个假设的情况,其中并不是 100% 清楚您期望的行为,但它可能与上面的代码不同。如果可能有一个 id (X1) 和日期组合,例如有 5 个观察值/行,并且其中三个时间相同,而两个时间不同,则这将适用。对于该 id-date 组合的所有观察结果,上面的代码将产生完全相同的 X4。如果您不想这样做,可以使用下面修改后的代码。我还将提供一个修改后的示例来演示该行为。

首先,我们创建一个新的数据集 test3 并修改它,使 X1 == 3162932date == 2014-01-03 有 4 个时间条目: 2 是相同的(所以对于那些 X4 应该用它的最大值替换)和 2 是不同的(所以对于那些我们应该用它们的 X4 之和替换 X4)。

test3 <- test2
test3$X1[1:4] <- "3162932"
test3$X3[2] <- "2014-01-03 8:47"

> test3
       X1         X2               X3  X4  # all 4 first rows have the same id
1 3162932 2014-01-03  2014-01-03 8:47  31   #   the first two are 
2 3162932 2014-01-03  2014-01-03 8:47  26   #     same id, same date, same time
3 3162932 2014-01-03 2014-01-03 10:11   4   #   this and the next are
4 3162932 2014-01-03 2014-01-03 11:44  32   #     same id, same date, different times
5 5374073 2014-01-04  2014-01-04 11:7  24
6 7427514 2014-01-03  2014-01-03 11:1 132
7 2377939 2014-01-11   2014-01-11 2:6  50
8 2377939 2014-01-11  2014-01-11 2:58  16
9 4081399 2014-01-07  2014-01-07 8:42  66

这是你可以按照我认为你想要的方式处理它的方法(但同样,你还没有真正指定这一点):

test3 %>%
  separate(X3, into = c("date", "time"), sep = " ") %>%
  mutate_each(funs(as.Date(., format = "%Y-%m-%d")), X2, date) %>%
  group_by(X1, date, time) %>%
  mutate(X4 = max(X4), check = n() == 1L) %>%
  group_by(X1, date) %>%
  mutate(X4 = ifelse(n_distinct(time) > 1L & check, sum(X4[check]), X4)) %>%
  ungroup() %>%
  unite(X3, date:time, sep = " ") %>%
  mutate(X3 = as.POSIXct(X3)) %>%
  select(ID = X1, Date = X2, DateTime = X3, Value = X4)

Source: local data frame [9 x 4]

       ID       Date            DateTime Value
1 3162932 2014-01-03 2014-01-03 08:47:00    31    # replaced by max
2 3162932 2014-01-03 2014-01-03 08:47:00    31    # replaced by max
3 3162932 2014-01-03 2014-01-03 10:11:00    36    # replaced by sum of 4 + 32
4 3162932 2014-01-03 2014-01-03 11:44:00    36    # replaced by sum of 4 + 32
5 5374073 2014-01-04 2014-01-04 11:07:00    24
6 7427514 2014-01-03 2014-01-03 11:01:00   132
7 2377939 2014-01-11 2014-01-11 02:06:00    66
8 2377939 2014-01-11 2014-01-11 02:58:00    66
9 4081399 2014-01-07 2014-01-07 08:42:00    66

关于r - 根据条件聚合 r,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27642890/

相关文章:

r - 错误 : Missing $ inserted when using kable

R:通过 XTS 对象与 Matrix 进行子选择:为什么这样的性能受到影响?

r - 根据唯一日期计算记录

r - 通过表格 y 轴上的组按组提取前 10 个值

Oracle:在分组结果中聚合连接未分组列的方法

r - 使用汇总(dplyr)的结果来变异原始数据帧

r - 创建名称数量不断增加的随机数据框列表

r - 从另一个 data.frame 中填充 data.frame 中的缺失值

json - 使用 jq 将五个单独的对象聚合到所需的输出

r - 如何使用 data.table 按日期(月、年、日)和子组汇总结果