我是R的新手,最近有一个项目来确定数据框中每个性别的十大最受欢迎的名字。 我有3列信息,我将其标记为“名称”,“性别”和“金额”。我认为我面临的最大问题是试图将所有男性聚集在一起,然后将所有女性聚集在“性别”栏目中。然后我的下一个问题是找到每个值的前10个值。任何帮助将非常感谢。
答案 0 :(得分:1)
您可以在R
中使用多种方式执行此操作。
在base R
中,您可以使用一些常规的分组和提取技术,例如ave
,by
或aggregate
等。在下面显示的方法中,我首先按列sex
和amount
按amount
降序排列数据(请注意-
符号)。然后,我使用ave
来获得前10个观测值的逻辑索引。
dat1 <- dat[order(dat$sex, -dat$amount),]
indx <- with(dat1, ave(seq_along(amount), sex, FUN=seq_along) %in% 1:10)
indx
# [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE FALSE FALSE
# [13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
# [25] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE FALSE FALSE
# [37] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
# [49] FALSE FALSE
dat1[indx,]
或者,我们也可以使用10
,head
函数
by
行
do.call(rbind, by(dat1, list(dat1$sex), FUN=head,10))
要详细了解这些功能,请在R控制台中执行?<function>
,例如?ave
,了解该功能及其用法。
您还可以使用其他包来完成任务。如果您的数据集非常大。我建议dplyr
或data.table
执行此操作,因为它可以有效处理大数据集。
在下面的代码中,我使用的是最新版本的dplyr
,即dplyr 0.3
。你可以从github project page of dplyr获得它。
devtools::install_github("hadley/dplyr")
library(dplyr)
library(tidyr)
dplyr
中的操作使用链%>%
来连接不同的操作。在下面的代码中,我们首先将dat
分组为sex
,然后按顺序排序amount
变量,并在最后一步使用slice
获取前10行每个sex
。在dplyr 0.2
中,您可以使用dO(head(., 10)
代替。
dat %>%
group_by(sex) %>%
arrange(desc(amount)) %>%
slice(1:10) #do(head(., 10) #in `dplyr 0.2`
给出结果
# name sex amount
#1 N F 98
#2 R F 97
#3 Q F 97
#4 T F 95
#5 S F 91
#6 A F 91
#7 Y F 89
#8 Z F 87
#9 T F 85
#10 Y F 85
#11 X M 98
#12 Q M 97
#13 K M 96
#14 O M 90
#15 A M 90
#16 X M 86
#17 D M 84
#18 V M 84
#19 C M 83
#20 X M 78
就速度而言,in documented cases,data.table
效率很高。在这里,我们的想法是按照amount
列按降序排序数据(请注意-
),组按分类对有序数据进行排序,对于每个组子集使用.SD
的前10行,表示Subset of Data.table
。
library(data.table)
setDT(dat)[order(-amount), .SD[1:10], by=sex] ## or head(.SD, 10L)
注意:如果您使用的是data.frame
,则可以使用
data.table
DT <- as.data.table(dat)
或者,您也可以setDT
转换为data.table
。它会将data.frame
转换为data.table
引用(无任何额外的副本/内存使用情况),如上所示。
set.seed(42)
dat <- data.frame(name=sample(LETTERS, 50, replace=TRUE),
sex=sample(c("M", "F"), 50, replace=TRUE), amount=sample(40:100, 50, replace=TRUE))