2016-09-06 109 views
1

我在R中有一个名为data的列表。数据具有列CustIDEndDate删除带条件的重复条目列表R

我想要做的就是搜索比较CustID的列表以找到与CustID相同的重复条目。

在找到的条目上,我想比较EndDate,并从列表中删除最低值(最旧的EndDate)的条目。

我有,因为我不是很习惯在R.具有这些功能的工作

+2

请为您的列表提供一个可再现的小例子,例如使用'dput()' – Jimbou

+4

它是一个'list'还是'data.frame'?请检查[如何创建一个最小可重现的例子](http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example)并更新您的问题 –

+0

澄清原因@ docendodiscimus问这是因为列表没有列。所以目前还不清楚你的意思是列表元素,还是你的意思是data.frame的列。 –

回答

1
CustID <- c(seq(1,10,1),seq(1,5,1)) 
EndDate <- c(Sys.Date(),rep(seq(Sys.Date(),Sys.Date()+6, 1),2)) 

# Let's assume you're starting with a list 
data <- list(CustID, EndDate) 

名单如何处理这个问题,不知道是这样的:

[[1]] 
[1] 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 

[[2]] 
[1] "2016-09-06" "2016-09-06" "2016-09-07" "2016-09-08" "2016-09-09" "2016-09-10" "2016-09-11" "2016-09-12" "2016-09-06" 
[10] "2016-09-07" "2016-09-08" "2016-09-09" "2016-09-10" "2016-09-11" "2016-09-12" 
# To make matching CustID and EndDate easy let's change it to a DF 
df1   <- as.data.frame(data) 
colnames(df1) <- c("CustID", "EndDate") 

data.frame看起来像这样:

CustID EndDate 
1  1 2016-09-06 
2  2 2016-09-06 
3  3 2016-09-07 
4  4 2016-09-08 
5  5 2016-09-09 
6  6 2016-09-10 
7  7 2016-09-11 
8  8 2016-09-12 
9  9 2016-09-06 
10  10 2016-09-07 
11  1 2016-09-08 
12  2 2016-09-09 
13  3 2016-09-10 
14  4 2016-09-11 
15  5 2016-09-12 
# Find duplicated CustID 
dupID <- duplicated(df1$CustID) 
dupdf <- df1[df1$CustID %in% df1$CustID[dupID],] 

# Remove the entry with the oldest EndDate for each ID 
res <- data.frame(CustID=NA, EndDate = as.Date(NA)) 

for(i in unique(dupdf$CustID)){ 
    tmp <- dupdf[dupdf$CustID == i, ] 
    res <- rbind(res,tmp[!tmp$EndDate == min(tmp$EndDate),]) 
} 
res <- res[!is.na(res$EndDate),] 

结果(res)具有重复客户的ID(custID)与最古老的EndDate每个ID删除:

CustID EndDate 
11  1 2016-09-08 
12  2 2016-09-09 
13  3 2016-09-10 
14  4 2016-09-11 
15  5 2016-09-12 

如果你想有一个矢量您可能使用的解决方案data.table

require(data.table) 
dupdf <- data.table(dupdf) 
dupdf[,.(
    EndDate = max(EndDate) 
), by = CustID] 

从注释一个建议是

data <- as.data.frame(data) 
subset(data, as.logical(ave(as.numeric(EndDate), CustID, FUN = function(x) { 
    length(x) == 1L | x != min(x) 
}))) 
+0

谢谢你,善良的先生! –

+0

@ P.Berg乐于帮助!干杯 –

+3

在一个循环动态增长的对象(如你用'res'做的)是不是真的值得推荐的做法 –

0

下面是使用dplyr包的溶液

data <- list(CustID=c(seq(1,10,1),seq(1,5,1),3,3,3), 
     EndDate=c(Sys.Date(), 
        rep(seq(Sys.Date(),Sys.Date()+6, 1),2), 
        Sys.Date()+6, Sys.Date()+6, Sys.Date()+10 
        )) 

#Convert list to data frame and remove oldest duplicates 
data %>% 
    do.call(cbind.data.frame,.) %>% 
    group_by(CustID) %>% 
    summarise_all(funs(last)) %>% 
    ungroup 

ID“3”出现5次,包括在天重复该会被保留。根据传递的参数,“汇总”功能将分组变量(在此情况下为ClustID)减少为单个观察值。在这种情况下,“最后”功能会保留最近的观察,忽略同一天的重复。

如果您的数据不是按时间顺序排列,请使用arrange(desc(EndDate))来排序数据。

+0

如果你有多列并且不想汇总所有,总结(EndDate = last(EndDate)) –

+1

提取最后日期不同于删除第一个日期,因为每个ID可能有多于2个条目。 (你可以做'data%>%data.frame()%>%...') –

+0

你的意思是我应该按时间顺序排列它们吗? “安排(结束日期)”?然后,数据可能会有多个条目按客户ID排序,并且初始排序也不相关。 –