如何在给定时间段内根据多个条件拒绝重复值

时间:2018-03-13 13:44:47

标签: r date dataframe

我的数据如下所示:

.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

4 个答案:

答案 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'))