【问题标题】:Determining the 10 highest values of two levels in a column of a dataframe确定数据框列中两个级别的 10 个最高值
【发布时间】:2014-10-03 13:38:28
【问题描述】:

我对 R 非常陌生,最近有一个项目可以确定数据框中每个性别的前 10 个最受欢迎的名字。 我有 3 列信息,分别标有“姓名”、“性别”和“金额”。我认为我面临的最大问题是试图将所有男性分组在一起,然后将所有女性分组在“性别”列中。然后我的下一个问题是找到每个值的前 10 个值。任何帮助将不胜感激。

【问题讨论】:

  • 这是你的作业吗?

标签: r


【解决方案1】:

您可以在R 中使用多种方式来完成此操作。

基础 R:

base R 中,您可以使用一些常规的分组和提取技术,例如avebyaggregate 等。在下面显示的方法中,我首先按列对数据进行排序@987654328 @ 和 amountamount 按降序排列(注意 - 符号)。然后,我使用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,]

或者,我们也可以通过使用headby 函数的组合来获取第一行10

 do.call(rbind, by(dat1, list(dat1$sex), FUN=head,10))

要了解有关这些功能的更多信息,请在 R 控制台中执行 ?&lt;function&gt;,例如,?ave 以了解该功能及其用法。


您还可以使用其他软件包来完成任务。如果你的数据集真的很大。我建议通过dplyrdata.table 执行此操作,因为它在处理大型数据集时非常有效。

dplyr:

在下面的代码中,我使用的是最新版本的dplyr,即dplyr 0.3。您可以从github project page of dplyr 获取。

devtools::install_github("hadley/dplyr")
library(dplyr)
library(tidyr)

dplyr 中的操作使用链 %&gt;% 连接不同的操作。在下面的代码中,我们首先将datsex 分组,然后对amount 变量进行降序排序,最后使用slice 得到每个sex 的前10 行。在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 casesdata.table 效率很高。同样,这里的想法是按amount 列以降序对数据进行排序(注意-),group by 对有序数据进行分组,并为每个组子集使用前 10 行.SD 表示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))

【讨论】:

  • @pumpkintea 您的代码与我在这里展示的任何代码都不同。当您说我的建议不起作用时,不清楚吗?您可以将代码复制并粘贴到您的帖子中,并使用dput 将其与示例数据集一起更新,正如我在这里展示的那样。
  • 非常感谢您迄今为止的帮助!我似乎无法使用我的代码获得您的任何建议。这是我迄今为止尝试过的 apply(as.matrix(d),2,function(x) (as.matrix(d[,1],d[,2],d[,3])[order(d [,3],decreating=TRUE)[1:10]]) ) 这会按降序重新运行前 10 个姓名值,但不显示“性别”或“金额”。
  • @pumpkintea 我没有在这里显示任何apply(as.matrix(2))..
  • 我尝试使用 library(data.table) DT DT DT[order(-amount), .SD[1:10], by=sex] 错误:找不到对象 'DT'
  • @pumpkintea 您必须先安装包install.packages('data.table'),然后加载包library(data.table),然后再执行任何操作。这与除base R 之外的所有其他软件包有关。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-04
  • 2021-11-04
相关资源
最近更新 更多