按组排序变量(dplyr)

时间:2016-01-23 19:31:56

标签: r dplyr

我有一个包含x1, x2, group列的数据框,我希望生成一个新的数据框,其中包含一个额外的列rank,表示其组中x1的顺序。

有一个相关的问题here,但接受的答案似乎不再起作用了。

直到这里,没关系:

library(dplyr)
data(iris)
by_species <- iris %>% 
              arrange(Species, Sepal.Length) %>% 
              group_by(Species)  

但是当我试图按小组获得排名时:

by_species <- mutate(by_species, rank=row_number())

错误是:

  

排名错误(x,ties.method =&#34; first&#34;,na.last =&#34; keep&#34;):
  论证&#34; x&#34;缺少,没有默认

更新

问题是dplyrplyr之间存在冲突。要重现错误,请加载两个包:

library(dplyr)
library(plyr)
data(iris)
by_species <- iris %>% 
              arrange(Species, Sepal.Length) %>% 
              group_by(Species) %>% 
              mutate(rank=row_number())
# Error in rank(x, ties.method = "first", na.last = "keep") : 
# argument "x" is missing, with no default

卸载plyr它可以正常工作:

detach("package:plyr", unload=TRUE)
by_species <- iris %>% 
              arrange(Species, Sepal.Length) %>% 
              group_by(Species) %>% 
              mutate(rank=row_number())

by_species %>% filter(rank <= 3)

##   Sepal.Length Sepal.Width Petal.Length Petal.Width    Species  rank
##          (dbl)       (dbl)        (dbl)       (dbl)     (fctr) (int)
## 1          4.3         3.0          1.1         0.1     setosa     1
## 2          4.4         2.9          1.4         0.2     setosa     2
## 3          4.4         3.0          1.3         0.2     setosa     3
## 4          4.9         2.4          3.3         1.0 versicolor     1
## 5          5.0         2.0          3.5         1.0 versicolor     2
## 6          5.0         2.3          3.3         1.0 versicolor     3
## 7          4.9         2.5          4.5         1.7  virginica     1
## 8          5.6         2.8          4.9         2.0  virginica     2
## 9          5.7         2.5          5.0         2.0  virginica     3

2 个答案:

答案 0 :(得分:19)

以下内容将生成所需的结果。

library(dplyr)

by_species <- iris %>% arrange(Species, Sepal.Length) %>%
    group_by(Species) %>% 
    mutate(rank = rank(Sepal.Length, ties.method = "first"))

by_species %>% filter(rank <= 3)
##Source: local data frame [9 x 6]
##Groups: Species [3]
##
##  Sepal.Length Sepal.Width Petal.Length Petal.Width    Species  rank
##         (dbl)       (dbl)        (dbl)       (dbl)     (fctr) (int)
##1          4.3         3.0          1.1         0.1     setosa     1
##2          4.4         2.9          1.4         0.2     setosa     2
##3          4.4         3.0          1.3         0.2     setosa     3
##4          4.9         2.4          3.3         1.0 versicolor     1
##5          5.0         2.0          3.5         1.0 versicolor     2
##6          5.0         2.3          3.3         1.0 versicolor     3
##7          4.9         2.5          4.5         1.7  virginica     1
##8          5.6         2.8          4.9         2.0  virginica     2
##9          5.7         2.5          5.0         2.0  virginica     3

by_species %>% slice(1:3)
##Source: local data frame [9 x 6]
##Groups: Species [3]
##
##  Sepal.Length Sepal.Width Petal.Length Petal.Width    Species  rank
##         (dbl)       (dbl)        (dbl)       (dbl)     (fctr) (int)
##1          4.3         3.0          1.1         0.1     setosa     1
##2          4.4         2.9          1.4         0.2     setosa     2
##3          4.4         3.0          1.3         0.2     setosa     3
##4          4.9         2.4          3.3         1.0 versicolor     1
##5          5.0         2.0          3.5         1.0 versicolor     2
##6          5.0         2.3          3.3         1.0 versicolor     3
##7          4.9         2.5          4.5         1.7  virginica     1
##8          5.6         2.8          4.9         2.0  virginica     2
##9          5.7         2.5          5.0         2.0  virginica     3

答案 1 :(得分:2)

对于未来的读者,可以使用基数R来实现按组变量排名。根据OP的iris数据示例,根据Sepal.Length进行排名:

# ORDER BY SPECIES AND SEPAL.LENGTH
iris <- iris[with(iris, order(Species, Sepal.Length)), ]

# RUN A ROW COUNT FOR RANK BY SPECIES GROUP
iris$rank <- sapply(1:nrow(iris), 
                    function(i) sum(iris[1:i, c('Species')]==iris$Species[i]))

# FILTER DATA FRAME BY TOP 3
iris <- iris[iris$rank <= 3,]