R 在特定列上排序时如何进行分区?

R 在特定列上排序时如何进行分区?,r,dataframe,rank,database-partitioning,R,Dataframe,Rank,Database Partitioning,全部: 我有一个如下所示的数据框架。我知道我可以这样做一个全局排名顺序: 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

全部:

我有一个如下所示的数据框架。我知道我可以这样做一个全局排名顺序:

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
dt
ID值
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
美元订单
ID值顺序
1 A1 4 5
2 A2 3 3
3 A4 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
但是我如何为一个特定的ID设置一个等级顺序而不是一个全局等级顺序呢。我怎样才能做到这一点?在T-SQL中,我们可以通过以下语法完成此操作:

RANK() OVER ( [ < partition_by_clause > ] < order_by_clause > )
RANK()([]
有什么想法吗?

有很多选择

使用
plyr软件包中的
ddply

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
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
或者,如果性能是一个问题(即非常大的数据),请使用数据表包:

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
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

我的方式,但可能更好。从未使用过等级,我甚至不知道。谢谢,可能有用

#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]
编辑:

如果您不关心保留数据的原始顺序,那么使用更少的代码即可:

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

dt以下是几种方法:

ave这将获取具有相同ID的每组值编号,并将秩分别应用于每个此类集合。没有使用任何软件包

Rank <- function(x) rank(x, ties.method = "first")
transform(dt, rank = ave(Value, ID, FUN = Rank))
请注意,上述解决方案保持原始行顺序。如果需要的话,可以在以后对其进行排序

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"
')

此解决方案将对行重新排序。假设这是可以的,因为您的示例解决方案做到了这一点(但如果不将序号列附加到
dt
,并添加适当的order by子句以将结果重新排序到序号顺序中)。

您可以使用data.table包

setDT(dt)
dt[,Order:=rank(Value,ties.method=“first”),by=“ID”]

和往常一样,回答得很好。要从data.table获得最佳性能,最好尽可能避免使用
.SD
。对于大型data.tables(这是您最可能首先使用包的地方!):
DT我一直在尝试使用实现data.table解决方案,但每行的排名仅为1。我几乎一字不差地使用了您的代码,只是更改了变量名。你知道我可能会犯什么错误吗?我知道你看不到代码,所以这是一个很难回答的问题,但我不想重复这个问题。我想我应该在这里添加一条注释,说明
数据。table
现在提供了一个快速排名函数
frank
。。。应该会在你的
排名上面的地方下降很多。。。不幸的是,这对我来说仍然很慢,因为我正在与数百万个团体打交道。如果我找到一个更快的方法,我会发布更多。而不是那个丑陋的do.call(rbind(lappy()),使用专门设计的函数:
ave()
。有人能用dplyr重写这个吗?我知道这是很久以前的事了,但是你能详细介绍一下你的第一个方法吗?它似乎给了我表中每个条目一个等级。我只有我想按秒分组的列和我想在第一个参数中排名的列,就像你在这里看到的一样。我已经添加了一些解释和输出。
# 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"
')
   ID Value Order
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