我需要一个函数来检查我的数据框是否有相同的行,但日期减1,如果存在,则返回true
。它是一个庞大的数据框架,因此我希望尽可能高效地完成这项工作。
例如,请采用以下数据框:
name |date
Timmy |01/Jan/2016
Timmy |02/Jan/2016
Timmy |03/Jan/2016
Sally |04/Jan/2016
Johnny|13/Feb/2016
Johnny|29/Mar/2016
该功能应该看到Timmy|02/Jan/2016
,检查Timmy|01/Jan/2016
是否存在,然后返回true
。结果数据框如下所示:
name |date |hasDateMinusOne
Timmy |01/Jan/2016|false
Timmy |02/Jan/2016|true
Timmy |03/Jan/2016|true
Sally |04/Jan/2016|false
Johnny|13/Feb/2016|false
Johnny|29/Mar/2016|false
This is the closest answer I've found.虽然Hadley已经回答了这个问题,但它已经5岁了,并且早于dplyr。我想知道它是否仍然是处理1,000,000多行的最有效方式。
谢谢!
肖恩
答案 0 :(得分:2)
如果您将date
格式化为日期,则可以减去一个:
library(dplyr)
df %>% group_by(name) %>%
mutate(date = as.Date(date, '%d/%b/%Y'),
hasDateMinusOne = (date - 1) %in% date)
# Source: local data frame [6 x 3]
# Groups: name [3]
#
# name date hasDateMinusOne
# (fctr) (date) (lgl)
# 1 Timmy 2016-01-01 FALSE
# 2 Timmy 2016-01-02 TRUE
# 3 Timmy 2016-01-03 TRUE
# 4 Sally 2016-01-04 FALSE
# 5 Johnny 2016-02-13 FALSE
# 6 Johnny 2016-03-29 FALSE
答案 1 :(得分:1)
我们只能使用base R
执行此操作。使用transform
将“日期”转换为“日期”类,然后使用ave
按“名称”转换,并查找前一天是否找到%in%
“日期”列。< / p>
df <- transform(df, date = as.Date(date, "%d/%b/%Y"))
df$hasDateMinusOne <- with(df, !!ave(as.integer(date), name,
FUN = function(x) (x-1) %in% x))
如果效率很重要,另一种选择是data.table
。将'data.frame'转换为'data.table'(setDT(df)
),将'date'更改为'Date'类,按'name'分组,我们会发现前一天是否找到%in%
'日期'栏。
setDT(df)[, date := as.Date(date, '%d/%b/%Y')
][, hasDateMinusOne := (date-1) %in% date, by = name]
df
# name date hasDateMinusOne
#1: Timmy 2016-01-01 FALSE
#2: Timmy 2016-01-02 TRUE
#3: Timmy 2016-01-03 TRUE
#4: Sally 2016-01-04 FALSE
#5: Johnny 2016-02-13 FALSE
#6: Johnny 2016-03-29 FALSE