我的数据如下所示:
.pri
我正在尝试创建一个二进制列,该列反映给定的library(dplyr)
dat<-data_frame(Date=as.Date(c("2012-08-06","2012-08-06","2016-01-01","2016-12-20","2017-02-01","2015-02-03","2014-12-28","2017-06-06","2017-08-04","2017-10-28")),Person=c(1,1,2,2,2,3,3,4,4,4),Type=c("A","B","A","A","A","C","C","A","B","C"))
# A tibble: 10 x 4
Date Person Type
<date> <dbl> <chr>
1 2012-08-06 1 A
2 2012-08-06 1 B
3 2016-01-01 2 A
4 2016-12-20 2 A
5 2017-02-01 2 A
6 2015-02-03 3 C
7 2014-12-28 3 C
8 2017-06-06 4 A
9 2017-08-04 4 B
10 2017-10-28 4 C
是否是一年内给定Type
的给定Type
的第一个实例(基于{ {1}})。因此,在这种情况下,我将获得以下内容:
Person
答案 0 :(得分:3)
更新
我添加了一个检测周期重置的过程,我还修改了创建年份索引的过程,使其自动检测年份范围,因此您无需手动设置。
library(dplyr)
library(data.table)
library(tis)
#creating our data.table
dat <- data.table(Date=as.Date(c("2012-08-06","2012-08-06","2016-01-01","2016-12-20","2017-02-01","2017-03-01","2015-02-03","2014-12-28","2017-06-06","2017-08-04","2017-10-28")),Person=c(1,1,2,2,2,2,3,3,4,4,4),Type=c("A","B","A","A","A","A","C","C","A","B","C"))
#creating a year column to merge with year table
dat$year <- substring(dat$Date,1,4)
#creationg a year table with a number column which correspond to the number of the year among our list of year
year_table <- data.table(year=as.character(min(dat$year):max(dat$year)),number=1:length(min(dat$year):max(dat$year)))
#merging the two tables
dat <- year_table[dat,on = .(year)]
#seting the number to get exactly to which number correspond the date
dat$number <- dat$number + yday(dat$Date)/(365 + isLeapYear(as.numeric(dat$year)))
#creating min column by Person and Date which contains the value of min(number)
dat[,min:=ifelse(number==min(number),number,min(number)),by=list(Person,Type)][]
#calculation number - min and comapring it to 0 or 1
dat$diff <- dat$number - dat$min
#if diff==0, it's the first occurence so we set Original to 1, if 0<diff<1 set to 0 and if diff>1 set to 1
dat[,round_diff := trunc(diff)][] #Edit
dat[,temp_Original := ifelse(diff==0,1,ifelse(diff>0&diff<1,0,1)),by=list(Person,Type)][]
dat[,temp_Original2 := ifelse(diff>1 & diff>min(diff),0,1),by=list(round_diff,Type,Person)][] #Edit
dat[,Original := temp_Original*temp_Original2] #Edit
dat[,c("Date","Person","Type","Original")]
答案 1 :(得分:2)
使用data.table
- 包的可能替代解决方案:
# load the 'data.table' package
library(data.table)
# convert 'dat' to a 'data.table' and set the keys to 'Person' & 'Date'
# (which will reorder the data according to 'Person' & 'Date')
setDT(dat, key = c('Person','Date'))
# create a 'newgroup' variable for each person
# then check for duplicates by 'Person' & 'newgroup'
dat[, newgroup := cumsum(rowSums(abs(outer(Date, Date, '-')) > 365)), by = Person
][, original := +(!duplicated(Type)), by = .(Person, newgroup)
][, newgroup := NULL][]
给出:
Date Person Type original 1: 2012-08-06 1 A 1 2: 2012-08-06 1 B 1 3: 2016-01-01 2 A 1 4: 2016-12-20 2 A 0 5: 2017-02-01 2 A 1 6: 2014-12-28 3 C 1 7: 2015-02-03 3 C 0 8: 2017-06-06 4 A 1 9: 2017-08-04 4 B 1 10: 2017-10-28 4 C 1
答案 2 :(得分:1)
这是一个dplyr
解决方案。
我们首先定义一个自定义函数,它需要多年的YYYYMMDD格式和标志,并在间隔超过10000时重新启动一行(因此处理闰年)。
然后我们将其用于相关群组。
library(dplyr)
new_year <- function(x) {
is_new <- 1
if(length(x)>1){
base <- x[1]
for (i in 2:length(x)) {
interval <- x[i] - base
if (interval >= 10000) {
is_new <- c(is_new,1)
base <- x[i]
} else {
is_new <- c(is_new,0)
}
}
}
return (is_new)
}
dat %>%
arrange(Date) %>%
group_by(Person,Type) %>%
do({mutate(., Original=new_year(year(Date)*10000+month(Date)*100+day(Date)))}) %>%
right_join(dat)
# Joining, by = c("Date", "Person", "Type")
# # A tibble: 10 x 4
# # Groups: Person, Type [?]
# Date Person Type Original
# <date> <dbl> <chr> <dbl>
# 1 2012-08-06 1 A 1
# 2 2012-08-07 1 B 1
# 3 2016-01-01 2 A 1
# 4 2016-12-20 2 A 0
# 5 2017-02-01 2 A 1
# 6 2015-02-03 3 C 0
# 7 2014-12-28 3 C 1
# 8 2017-06-06 4 A 1
# 9 2017-08-04 4 B 1
# 10 2017-10-28 4 C 1
答案 3 :(得分:1)
这是另一种仅使用dplyr的解决方案。我按人和类型得到了原始日期,将其加入到现有数据集中,然后检查日期是否在原始日期的一年内且不等于自身。
更新 - 我更改了dat3步骤以回答下面的评论。我为重置日期添加了一个额外的列,并更改了datediff变量的逻辑。
library(dplyr)
dat<-data_frame(Date=as.Date(c("2012-08-06","2012-08-06","2016-01-01","2016-12-20",
"2017-02-01","2015-02-03","2014-12-28",
"2017-06-06","2017-08-04","2017-10-28")),
Person=c(1,1,2,2,2,3,3,4,4,4),
Type=c("A","B","A","A","A","C","C","A","B","C"))
dat2 <- dat %>%
arrange(Date, Person) %>%
group_by(Person, Type) %>%
filter(row_number() ==1) %>%
mutate(FirstDate = Date) %>%
select(-Date)
dat3 <- left_join(dat, dat2, by = c("Person"= "Person", "Type" = "Type")) %>%
mutate(Original = ifelse(Date == FirstDate, 1,
ifelse(Date - FirstDate <= 365, 0 ,1)),
datediff = ifelse(Date - FirstDate >= 365, 0, Date - FirstDate),
ResetDate = as.Date(ifelse(Date - FirstDate > 365 & Original == 1, Date,
FirstDate), origin = '1970-01-01'))