我的数据集包含四列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
替换为max
x4
。例如,身份证号码(549395)具有相同的日期和时间(x3)6/4/2014 11:10,因此X4
应替换为max(72, 8) ...72
。
如果X1
(ID号)具有相同的日期但时间不同,则将其对应的X4
替换为其各个x4的sum
。例如,身份证号码(845277)具有相同的日期(2014年4月7日)不同时间(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
答案 0 :(得分:1)
这里有一个选项,你可以使用dplyr和tidyr来做到这一点。我包含了一些日期格式,这会增加" pipe"的长度,但它值得IMO。我将管道的那些部分标记为"可选"。
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%清楚你期望的行为,但它可能与上面的代码有所不同。如果可能存在例如5个观察/行的id(X1)和日期组合,并且其中三个时间相同并且两个时间不同,则这将适用。对于该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
答案 1 :(得分:1)
这是一个稍微简单的逻辑,使用data.table
实现:
require(data.table)
setDT(test2)[, tmp := NA]
test2[, c("X4", "tmp") := if (.N > 1) list(max(X4), TRUE), by=.(X1, X3)] ## (1)
test2[is.na(tmp), X4 := sum(X4), by=.(X1, gsub(" .*$", "", X3))] ## (2)
# X1 X2 X3 X4 tmp
# 1: 1491930 2014-01-03 2014-01-03 8:47 31 NA
# 2: 3162932 2014-01-03 2014-01-03 9:40 30 NA
# 3: 3162932 2014-01-03 2014-01-03 10:11 30 NA
# 4: 4092879 2014-01-03 2014-01-03 11:44 32 NA
# 5: 5374073 2014-01-04 2014-01-04 11:7 24 NA
# 6: 7427514 2014-01-03 2014-01-03 11:1 132 NA
# 7: 2377939 2014-01-11 2014-01-11 2:6 66 NA
# 8: 2377939 2014-01-11 2014-01-11 2:58 66 NA
# 9: 4081399 2014-01-07 2014-01-07 8:42 66 NA
通过引用将test2
从data.frame转换为data.table(无需任何其他副本)。现在test2
是一个data.table,我们可以使用data.table语法。然后我们使用NA
添加一个新的(虚拟)列(作为标记)。
按X1
和X3
列进行汇总。如果有多行,则这些行属于您的第一个条件。我们已根据X4
的最大值单独替换这些行。我们在(1)中执行此操作,但此外,我们还将这些行的虚拟列更新为TRUE。
然后,我们按X1
分组,只分组X3
的日期部分,但仅限于上一步中未修改的行。这些满足你的第二个条件。我们将X4
替换为该组中所有值的总和。
这也应该考虑到你的行满足给定X1
和日期的两个条件的情况。
如有必要,您可以将tmp
列设置为NULL
:
test2[, tmp := NULL]