Rob*_*Min 14 r rank database-partitioning dataframe
所有:
我有一个类似于follow的数据框.我知道我可以做这样的全局排名顺序:
dt <- data.frame(
ID = c('A1','A2','A4','A2','A1','A4','A3','A2','A1','A3'),
Value = c(4,3,1,3,4,6,6,1,8,4)
);
> dt
ID Value
1 A1 4
2 A2 3
3 A4 1
4 A2 3
5 A1 4
6 A4 6
7 A3 6
8 A2 1
9 A1 8
10 A3 4
dt$Order <- rank(dt$Value,ties.method= "first")
> dt
ID Value Order
1 A1 4 5
2 A2 3 3
3 A4 1 1
4 A2 3 4
5 A1 4 6
6 A4 6 8
7 A3 6 9
8 A2 1 2
9 A1 8 10
10 A3 4 7
Run Code Online (Sandbox Code Playgroud)
但是,如何为特定ID而不是全局排名顺序设置排名顺序.我怎么能这样做?在T-SQL中,我们可以按照以下语法完成此操作:
RANK() OVER ( [ < partition_by_clause > ] < order_by_clause > )
Run Code Online (Sandbox Code Playgroud)
任何的想法?
jor*_*ran 13
很多选择.
使用ddply从plyr包:
library(plyr)
ddply(dt,.(ID),transform,Order = rank(Value,ties.method = "first"))
ID Value Order
1 A1 4 1
2 A1 4 2
3 A1 8 3
4 A2 3 2
5 A2 3 3
6 A2 1 1
7 A3 6 2
8 A3 4 1
9 A4 1 1
10 A4 6 2
Run Code Online (Sandbox Code Playgroud)
或者,如果使用data.table包,性能是一个问题(即非常大的数据):
library(data.table)
DT <- data.table(dt,key = "ID")
DT[,transform(.SD,Order = rank(Value,ties.method = "first")),by = ID]
ID Value Order
[1,] A1 4 1
[2,] A1 4 2
[3,] A1 8 3
[4,] A2 3 2
[5,] A2 3 3
[6,] A2 1 1
[7,] A4 1 1
[8,] A4 6 2
[9,] A3 6 2
[10,] A3 4 1
Run Code Online (Sandbox Code Playgroud)
或者在其所有的血腥细节中使用split lapply do.call和的基本R解决方案rbind:
do.call(rbind,lapply(split(dt,dt$ID),transform,
Order = rank(Value,ties.method = "first")))
Run Code Online (Sandbox Code Playgroud)
以下是几种方法:
ave 这将获取具有相同ID的每组值数字,并将等级分别应用于每个这样的集合.没有使用包裹.
Rank <- function(x) rank(x, ties.method = "first")
transform(dt, rank = ave(Value, ID, FUN = Rank))
Run Code Online (Sandbox Code Playgroud)
赠送:
ID Value rank
1 A1 4 1
2 A2 3 2
3 A4 1 1
4 A2 3 3
5 A1 4 2
6 A4 6 2
7 A3 6 2
8 A2 1 1
9 A1 8 3
10 A3 4 1
Run Code Online (Sandbox Code Playgroud)
请注意,上述解决方案保留原始行顺序.如果需要,可以在之后进行分类.
sqldf与RPostgreSQL
# see FAQ #12 on the sqldf github home page for info on sqldf and PostgreSQL
# https://cran.r-project.org/web/packages/sqldf/README.html
library(RPostgreSQL)
library(sqldf)
sqldf('select
*,
rank() over (partition by "ID" order by "Value") rank
from "dt"
')
Run Code Online (Sandbox Code Playgroud)
此解决方案重新排序行.假设这是正确的,因为您的示例解决方案就是这样(但如果没有附加序列号列dt并添加适当的order by子句以将结果重新排序回序列号顺序).
我的方式,但可能有更好的。没用过等级,甚至不知道。谢谢,可能有用。
#Your Data
dt <- data.frame(
ID = c('A1','A2','A4','A2','A1','A4','A3','A2','A1','A3'),
Value = c(4,3,1,3,4,6,6,1,8,4)
)
dt$Order <- rank(dt$Value,ties.method= "first")
#My approach
dt$id <- 1:nrow(dt) #needed for ordering and putting things back together
dt <- dt[order(dt$ID),]
dt$Order.by.group <- unlist(with(dt, tapply(Value, ID, function(x) rank(x,
ties.method = "first"))))
dt[order(dt$id), -4]
Run Code Online (Sandbox Code Playgroud)
产量:
ID Value Order Order.by.group
1 A1 4 5 1
2 A2 3 3 2
3 A4 1 1 1
4 A2 3 4 3
5 A1 4 6 2
6 A4 6 8 2
7 A3 6 9 2
8 A2 1 2 1
9 A1 8 10 3
10 A3 4 7 1
Run Code Online (Sandbox Code Playgroud)
编辑:
如果您不关心保留数据的原始顺序,那么这可以使用更少的代码:
dt <- dt[order(dt$ID),]
dt$Order.by.group <- unlist(with(dt, tapply(Value, ID, function(x) rank(x,
ties.method= "first"))))
ID Value Order.by.group
1 A1 4 1
5 A1 4 2
9 A1 8 3
2 A2 3 2
4 A2 3 3
8 A2 1 1
7 A3 6 2
10 A3 4 1
3 A4 1 1
6 A4 6 2
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
15613 次 |
| 最近记录: |