2016-09-01 2 views
1

У меня следующая таблица в R dataframeфлажков данных в пределах групп в R dataframe

enter image description here

Я хотел бы написать логику, которая генерирует столбец «сохранить». Для каждого человека я хотел бы отметить учетные записи, у которых есть транзакция более чем на 4 дня, начиная с первого доступа. Итак, первая строка - это новая учетная запись для этого человека, поэтому отметьте ее. Вторая строка датирует всего 2 дня, так что держите ее тоже. Третья строка - 11 дней с тех пор, как мы впервые увидели эту учетную запись, чтобы мы не отметили ее. Та же логика касается следующего человека. Флаг только для учетных записей, возраст которых составляет менее 4 дней.

ответ

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

Ваша логика прекрасна, но я думаю, что вы можете немного конденсировать код: 'df%>% group_by (Person)%>% mutate (keep = as.numeric (date2 - first (date2) <= 4)) %>% select (- date2) 'например. – thelatemail

+0

Ну, это определенно более элегантно. Я редактирую свой ответ. – thepule

1

Использование data.table:

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

Мы группа по Person, а затем создать столбец Keep используя условие, что date меньше 4 дней с first(date) для 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") 

Результат является:

## Person  date account Keep 
##1 abc 2016-04-01  123  1 
##2 abc 2016-04-03  123  1 
##3 abc 2016-04-12  123  0 
##4 eee 2016-05-03  222  1 
##5 eee 2016-05-04  222  1 
##6 eee 2016-05-04  333  1 
##7 eee 2016-05-06  222  1 
##8 eee 2016-05-10  333  0 
+1

@Frank Спасибо, я исправлю это. – aichao

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 счета первого обнаружился.

+0

Забыл включить дату в сортировку, она должна быть 'организовать (Person, account, date2)%>%' – user3482393

Смежные вопросы