我的数据集包含四列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
我想要完成的是这个
如果
X1
(ID 号)在X3
中具有相同的日期和时间,则将其对应的X4
替换为其中
。例如,身份证号码 (549395 ) 具有相同的日期和时间 (x3) 6/4/2014 11:10,因此x4
的最大值X4
应替换为max(72, 8) ... 72
.如果
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 == 3162932
和 date == 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/