按两列排名并保持联系

时间:2017-01-03 16:36:58

标签: r data.table dplyr rank

我的问题是此探测的继续Link

我有一个这样的数据集:

JSONArray items = new JSONArray(jsonStr );

我想按照参考日期对每个日期进行排名 - 2015年1月31日。与参考日期最接近的日期排名为1,排名第二,依此类推。结果如下:

 ID    |     Date 

  A        01/01/2015
  A        02/01/2015
  A        02/01/2015
  A        02/01/2015
  A        05/01/2015     
  B        01/01/2015

虽然排名功能确实存在,但我也希望保持所有联系。我怎么做?

另外,我正在处理一个庞大的数据集 - 约。 3亿行。所以解决方案理想情况下会很快。

4 个答案:

答案 0 :(得分:2)

我们可以使用frank的{​​{1}} data.table dense作为ties.method,然后按ID' ID'关于日期'日期'之间的abs olute差异和参考日期(' 2015-01-31')

library(data.table)
setDT(df)[, Sequence := frank(abs(as.IDate(Date, "%d/%m/%Y")- 
              as.IDate("2015-01-31")), ties.method = "dense"), by = ID]
df
#    ID       Date Sequence
#1:  A 01/01/2015        3
#2:  A 02/01/2015        2
#3:  A 02/01/2015        2
#4:  A 02/01/2015        2
#5:  A 05/01/2015        1
#6:  B 01/01/2015        1

数据

df <- structure(list(ID = c("A", "A", "A", "A", "A", "B"), Date = c("01/01/2015", 
 "02/01/2015", "02/01/2015", "02/01/2015", "05/01/2015", "01/01/2015"
)), .Names = c("ID", "Date"), class = "data.frame", row.names = c(NA, 
-6L))

答案 1 :(得分:2)

使用dplyr dense_rank

library(dplyr)
df$Sequence <- dense_rank(as.numeric(as.Date('31/01/2015', '%d/%m/%Y') - as.Date(df$Date, '%d/%m/%Y')))
head(df) 

  ID       Date Sequence
1  A 01/01/2015        3
2  A 02/01/2015        2
3  A 02/01/2015        2
4  A 02/01/2015        2
5  A 05/01/2015        1
6  B 01/01/2015        3

答案 2 :(得分:1)

这是一个可行的data.table方法。

rleid按组ID返回同一日期的“ID”。但是,这些ID从0开始计数。在第二个链中,[(max(var) - var) + 1L会反转每个ID组的这些日期ID。

df[, var:=rleid(Date), by=ID][, var := (max(var) - var) + 1L, by=ID]
df
   ID       Date var
1:  A 01/01/2015   3
2:  A 02/01/2015   2
3:  A 02/01/2015   2
4:  A 02/01/2015   2
5:  A 05/01/2015   1
6:  B 01/01/2015   1

答案 3 :(得分:1)

基础R解决方案。首先通过将它们转换为Date个对象并获取差异的绝对值来获取您的日期和目标日期。

timediff <- abs(as.Date(df[["Date"]], format = "%d/%m/%Y") - as.Date("2015-01-31"))

接下来,我们可以使用rank来获取它们的顺序。我们可以使用为关系生成单个值的任何ties.method,但"min""max"可能是最好的,因为它们输出整数。

diffrank <- rank(timediff, ties.method = "min")

最后,我们可以使用this solution重新排序排名,以消除实例之间的差距。

df[["Sequence"]] <- as.numeric(factor(diffrank))

如果您愿意,可以在一行中完成:

df[["Sequence"]] <- as.numeric(factor(rank(
                        abs(as.Date(df[["Date"]], format = "%d/%m/%Y") - 
                               as.Date("2015-01-31")), ties.method = "min")))