如何在 R 中使用 Group By 和排序函数
How do I use Group By with order function in R
我有一个包含 120000 条记录和 19 个变量的数据框,其中 2 个是 state 和 MonthlyIncome。
我必须创建一个新数据集,其中包含每个州的前 10 名(按月收入计算)客户。
我尝试了很多选项,包括 data.table 和 dplyr 和 base,但总是缺少一些东西。
data.table :
x <- customer_any_360[,order(-dense_rank(MonthlyIncome))[1:10], by = state]
--- 我试过的例子
有人可以帮忙吗,我对 R 还是个新手,真的在为这个问题苦苦挣扎。提前致谢!!
在令人惊叹的 data.table
包中寻找答案,您就走在了正确的轨道上。这里我只是编造了一些状态 1 到 50 的数据,并从正态分布 N(50000, 20000^2) 中提取收入。
根据@Arun 的 评论进行编辑,并从 OP 请求所有列(使用 .SD 隐藏变量):
require(data.table)
set.seed(123)
mydata <- data.table(state = 1:50,
monthlyIncome = round(rnorm(120000, 50000, 20000)),
anothervar = 1:120000)
selecteddata <- mydata[order(-monthlyIncome), head(.SD, 10), by = state]
# just to verify
selecteddata <- selecteddata[order(state, -monthlyIncome)]
mydata <- mydata[order(-monthlyIncome)]
identical(selecteddata[1:10], mydata[state==1][1:10]) # state 1
identical(selecteddata[11:20], mydata[state==2][1:10]) # state 2
如果您想使用 rank
函数,一个选项是 data.table
中的 frank
,您可以在 ties.method
中指定选项。
library(data.table)#v1.9.5+
setDT(customer_any_360)[, .SD[frank(-MonthlyIncome,
ties.method='dense') %in% 1:10], by = state]
甚至 order
就足够了
setDT(customer_any_360)[order(-MonthlyIncome), .SD[1:10], by = state]
使用dplyr
,有多个选项,dense_rank
、min_rank
、top_n
,这取决于你想要什么。此外,对于过滤,可以使用 slice
或 filter
。
library(dplyr)
customer_any_360 %>%
group_by(state) %>%
slice(dense_rank(-MonthlyIncome)[1:10])
或使用sqldf
library(sqldf)
sqldf('select * from customer_any_360 i
where rowid in
(select rowid from customer_any_360
where state = i.state
order by MonthlyIncome desc
limit 10)
order by i.state, i.MonthlyIncome desc')
或使用 base R
中的 ave
indx <- with(customer_any_360, ave(-MonthlyIncome, state,
FUN=function(x) rank(x, ties.method='first')) %in% 1:10)
customer_any_360[indx,]
编辑:frank
选项根据@Arun
的建议进行了编辑
数据
set.seed(24)
customer_any_360 <- data.frame(cust=1:120000, state= sample(state.abb,
120000, replace=TRUE), MonthlyIncome= sample(1000:6500, 120000,
replace=TRUE), stringsAsFactors=FALSE)
使用 plyr 包中的 ddply:
data(iris)
ddply(iris, "Species", function(x) head(x[order(x$Sepal.Length, decreasing = TRUE) , ], 2))
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1 5.8 4.0 1.2 0.2 setosa
2 5.7 4.4 1.5 0.4 setosa
3 7.0 3.2 4.7 1.4 versicolor
4 6.9 3.1 4.9 1.5 versicolor
5 7.9 3.8 6.4 2.0 virginica
6 7.7 3.8 6.7 2.2 virginica
我有一个包含 120000 条记录和 19 个变量的数据框,其中 2 个是 state 和 MonthlyIncome。
我必须创建一个新数据集,其中包含每个州的前 10 名(按月收入计算)客户。
我尝试了很多选项,包括 data.table 和 dplyr 和 base,但总是缺少一些东西。
data.table :
x <- customer_any_360[,order(-dense_rank(MonthlyIncome))[1:10], by = state]
--- 我试过的例子
有人可以帮忙吗,我对 R 还是个新手,真的在为这个问题苦苦挣扎。提前致谢!!
在令人惊叹的 data.table
包中寻找答案,您就走在了正确的轨道上。这里我只是编造了一些状态 1 到 50 的数据,并从正态分布 N(50000, 20000^2) 中提取收入。
根据@Arun 的 评论进行编辑,并从 OP 请求所有列(使用 .SD 隐藏变量):
require(data.table)
set.seed(123)
mydata <- data.table(state = 1:50,
monthlyIncome = round(rnorm(120000, 50000, 20000)),
anothervar = 1:120000)
selecteddata <- mydata[order(-monthlyIncome), head(.SD, 10), by = state]
# just to verify
selecteddata <- selecteddata[order(state, -monthlyIncome)]
mydata <- mydata[order(-monthlyIncome)]
identical(selecteddata[1:10], mydata[state==1][1:10]) # state 1
identical(selecteddata[11:20], mydata[state==2][1:10]) # state 2
如果您想使用 rank
函数,一个选项是 data.table
中的 frank
,您可以在 ties.method
中指定选项。
library(data.table)#v1.9.5+
setDT(customer_any_360)[, .SD[frank(-MonthlyIncome,
ties.method='dense') %in% 1:10], by = state]
甚至 order
就足够了
setDT(customer_any_360)[order(-MonthlyIncome), .SD[1:10], by = state]
使用dplyr
,有多个选项,dense_rank
、min_rank
、top_n
,这取决于你想要什么。此外,对于过滤,可以使用 slice
或 filter
。
library(dplyr)
customer_any_360 %>%
group_by(state) %>%
slice(dense_rank(-MonthlyIncome)[1:10])
或使用sqldf
library(sqldf)
sqldf('select * from customer_any_360 i
where rowid in
(select rowid from customer_any_360
where state = i.state
order by MonthlyIncome desc
limit 10)
order by i.state, i.MonthlyIncome desc')
或使用 base R
ave
indx <- with(customer_any_360, ave(-MonthlyIncome, state,
FUN=function(x) rank(x, ties.method='first')) %in% 1:10)
customer_any_360[indx,]
编辑:frank
选项根据@Arun
数据
set.seed(24)
customer_any_360 <- data.frame(cust=1:120000, state= sample(state.abb,
120000, replace=TRUE), MonthlyIncome= sample(1000:6500, 120000,
replace=TRUE), stringsAsFactors=FALSE)
使用 plyr 包中的 ddply:
data(iris)
ddply(iris, "Species", function(x) head(x[order(x$Sepal.Length, decreasing = TRUE) , ], 2))
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1 5.8 4.0 1.2 0.2 setosa
2 5.7 4.4 1.5 0.4 setosa
3 7.0 3.2 4.7 1.4 versicolor
4 6.9 3.1 4.9 1.5 versicolor
5 7.9 3.8 6.4 2.0 virginica
6 7.7 3.8 6.7 2.2 virginica