在R数据帧中标记组内的数据

时间:2016-09-01 21:16:51

标签: r date counting

我在R dataframe

中有以下表格

enter image description here

我想编写生成“保持”列的逻辑。对于每个人,我想标记自首次访问以来交易时间超过4天的帐户。所以第一行是这个人的新帐户,所以标记它。第二行日期只有2天,所以保持它。第三行是我们第一次看到这个帐号后的11天,所以我们不会标记它。同样的逻辑适用于下一个人。仅标记不到4天的帐户。

3 个答案:

答案 0 :(得分:1)

我重建了你的数据框,试试这个解决方案:

library(lubridate)
library(dplyr)

df <- data.frame(Person = c(rep("abc",3), rep("eee", 5)),
           date = c("4/1/2016", "4/3/2016", "4/12/2016", "5/3/2016", "5/4/2016","5/4/2016","5/6/2016", "5/10/2016"),
           account = c("123","123","123","222","222","333","222","333"), stringsAsFactors = F)

df$date2 <- mdy(df$date)

@thelatemail建议的最佳解决方案:

df %>% 
group_by(Person) %>% 
mutate(keep=as.numeric(date2 - first(date2) <= 4)) %>% 
select(-date2)

结果:

 Person      date account keep
1    abc  4/1/2016     123    1
2    abc  4/3/2016     123    1
3    abc 4/12/2016     123    0
4    eee  5/3/2016     222    1
5    eee  5/4/2016     222    1
6    eee  5/4/2016     333    1
7    eee  5/6/2016     222    1
8    eee 5/10/2016     333    0

我更复杂的原始解决方案(如果帐户创建日期不在每个人的第一行,则非常有用):

df %>% 
group_by(Person) %>% 
slice(which.min(date2)) %>%
select(Person, date2) %>%
rename(account_create = date2) %>%
merge(df, ., by = "Person") %>%
mutate(keep = as.numeric(date2 - account_create <= 4)) %>%
select(-c(date2, account_create))

答案 1 :(得分:1)

使用data.table

library(data.table)
setDT(df)[, Keep:=as.numeric(difftime(date,first(date),units="days") < 4), by=Person][]

我们按Person进行分组,然后使用Keep小于date4天的条件创建列first(date) {1}}。

在这里,我们假设Person列是date对象。如果date-time列作为字符串读入,那么我们可以使用:

进行转换
date

使用以下数据给出:

df$date <- as.POSIXct(df$date, format="%m/%d/%Y")

结果是:

df <- structure(list(Person = c("abc", "abc", "abc", "eee", "eee", 
"eee", "eee", "eee"), date = structure(c(1459483200, 1459656000, 
1460433600, 1462248000, 1462334400, 1462334400, 1462507200, 1462852800
), class = c("POSIXct", "POSIXt"), tzone = ""), account = c(123L, 
123L, 123L, 222L, 222L, 333L, 222L, 333L)), .Names = c("Person", 
"date", "account"), row.names = c(NA, -8L), class = "data.frame")

答案 2 :(得分:1)

感谢这些伟大的想法; R是惊人的,在四行代码中进行相对复杂的会计。我没有强调的另一件事是我还需要跟踪它是否是一个新帐户。此外,由于这些数据不一定排序,我先排序,所以这是最终版本。

    df %>% 
      arrange(Person,account) %>%
      group_by(Person,account) %>% 
      mutate(keep=as.numeric(date2 - first(date2) <4)) %>% 
      select(-date2)

结果:

    Person      date account  keep
    <chr>     <chr>   <chr> <dbl>
1    abc  4/1/2016     123     1
2    abc  4/3/2016     123     1
3    abc 4/12/2016     123     0
4    eee  5/3/2016     222     1
5    eee  5/4/2016     222     1
6    eee  5/6/2016     222     1
7    eee 5/10/2016     333     1
8    eee 5/11/2016     333     1

所以我们保留最后一行,因为距离333帐户首次出现只有1天。