按两列排名并保持联系
Rank by two columns and keep ties
我的问题是这个问题的延续Link
我有一个这样的数据集:
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
我想按参考日期 - 2015 年 1 月 31 日对每个日期进行排名。最接近参考日期的日期排在第 1 位,第二位排在第 2 位,依此类推。结果如下:
ID | Date | Sequence
A 01/01/2015 3
A 02/01/2015 2
A 02/01/2015 2
A 02/01/2015 2
A 05/01/2015 1
B 01/01/2015 ...
虽然排名函数确实有想法,但我也想保持所有联系。我怎么做?
此外,我正在处理一个巨大的数据集 - 大约。 3亿行。因此,理想情况下,解决方案会很快。
这是一个可行的 data.table
方法。
rleid
returns "IDs" 相同日期按组 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
我们可以使用 data.table
中的 frank
和 dense
作为 ties.method
在按 'ID' 分组后 abs
olute 差异'Date'和参考日期('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))
与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
基本 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")))
我的问题是这个问题的延续Link
我有一个这样的数据集:
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
我想按参考日期 - 2015 年 1 月 31 日对每个日期进行排名。最接近参考日期的日期排在第 1 位,第二位排在第 2 位,依此类推。结果如下:
ID | Date | Sequence
A 01/01/2015 3
A 02/01/2015 2
A 02/01/2015 2
A 02/01/2015 2
A 05/01/2015 1
B 01/01/2015 ...
虽然排名函数确实有想法,但我也想保持所有联系。我怎么做?
此外,我正在处理一个巨大的数据集 - 大约。 3亿行。因此,理想情况下,解决方案会很快。
这是一个可行的 data.table
方法。
rleid
returns "IDs" 相同日期按组 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
我们可以使用 data.table
中的 frank
和 dense
作为 ties.method
在按 'ID' 分组后 abs
olute 差异'Date'和参考日期('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))
与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
基本 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")))