当从 data.table 或 head() 中选择 "top n" 列时,来自基础向量的 R returns 级别

When selecting "top n" columns from data.table or head(), R returns levels from underlying vector

我有一个df的钓鱼数据:

| year | taxon_name    | amount (tonnes) |
 1950    Gadus morhua    100
 1951    Gadus morhua    120
 1952    Gadus morhua    140
 1953    Gadus morhua    130
 1954    Gadus morhua    210
 1950    Sebastes        234
 1951    Sebastes        123
 1952    Sebastes        627
 1953    Sebastes        542
 1954    Sebastes        303

...等等

我知道如何使用几种方法 select 前 4 个捕捞物种,例如使用 data.table:

top4 <- setDT(discards_tax)[, .(amount = sum(amount)), by = taxon_name][order(-amount)][1:4, , ] # aggregate catch by taxon, order from highest to lowest catch & grab the top 4

或将 aggregateorderhead() 一起使用:

top4d <- aggregate(amount ~ taxon_name, discards_tax, sum) # aggregate catch by taxon
top4d <- top4d[order(-top4d$amount),] %>% head(4) # order df from highest to lowest catch & grab the top 4

两种情况都产生了这个成功的结果,旧的行号:

rowid | taxon_name                   | amount
   33   Melanogrammus aeglefinus       14922534
   60   Sebastes                       14274663
   25   Gadus morhua                   6237214
   53   Reinhardtius hippoglossoides   2466558

我的问题是,在此之后,我一直在尝试制作前 4 个 taxon_name 的矢量列表 - 但每次我都尝试这样做(即 toptaxa <- top4d$taxon_name) 它从我的钓鱼数据集中吐出了所有 67 个原始分类群!最初我认为这是 data.table 的一个设计特性,但看到无论我使用什么方法都会发生这种情况,很明显我没有正确理解它。

之前也有人问过类似的问题(例如 Why does selecting column(s) from a data.table results in a copy?),但我不确定我是否看到了让我 select 仅从我的结果中得到的答案。我怎样才能只操纵我的前 4 排序的结果?

编辑 这是我的数据集:https://www.dropbox.com/s/izn7sdpeosvg1nj/discards_for_stack.csv?dl=0

使用data.table方法。

library(data.table)
top4 <- setDT(df)[, .(amount = sum(amount)), by = taxon_name][order(-amount)][1:4, ]

toptaxa <- top4$taxon_name
#[1] "Sebastes"     "dummy2"       "dummy1"       "Gadus morhua"

Base-R聚合方法:

top4d <- aggregate(amount ~ taxon_name, df, sum)
top4d <- top4d[order(-top4d$amount),] %>% head(4)

toptaxa <- top4d$taxon_name

toptaxa
#[1] "Sebastes"     "dummy2"       "dummy1"       "Gadus morhua"

让我们检查另一个选项,使用 dplyr 包来汇总数据,最后使用 slice 获得前 4 个物种。

library(dplyr)

df %>% group_by(taxon_name) %>%
  summarise(amount = sum(amount.tonnes.)) %>%
  arrange(desc(amount)) %>%
  slice(1:4) %>%
  select(taxon_name) -> TopNames

#Check the result
TopNames

# # A tibble: 4 x 1
# taxon_name  
# <chr>       
# 1 Sebastes    
# 2 dummy2      
# 3 dummy1      
# 4 Gadus morhua

已编辑:使用 OP

共享的数据
df <- read.csv("D:\Learning\R\discards_for_stack.csv", header = TRUE, stringsAsFactors = FALSE)
top4d <- aggregate(amount ~ taxon_name, df, sum)
top4d <- top4d[order(-top4d$amount),] %>% head(4)

top4d
#                      taxon_name   amount
# 33     Melanogrammus aeglefinus 14922534
# 60                     Sebastes 14274663
# 25                 Gadus morhua  6237214
# 53 Reinhardtius hippoglossoides  2466558

toptaxa <- top4d$taxon_name
toptaxa
# [1] "Melanogrammus aeglefinus"     "Sebastes"                     "Gadus morhua"                
# [4] "Reinhardtius hippoglossoides"

数据:在 OP 玩具数据集中添加了一些额外的行来制作一个合理的示例。

df <- read.table(text = 
"year  taxon_name     amount(tonnes)
1950    'Gadus morhua'    100
1951    'Gadus morhua'    120
1952    'Gadus morhua'    140
1953    'Gadus morhua'    130
1954    'Gadus morhua'    210
1950    Sebastes        234
1951    Sebastes        123
1952    Sebastes        627
1951    dummy1        123
1952    dummy1        627
1951    dummy2        567
1952    dummy2        627
1951    dummy3        567
1952    dummy4        627
1953    Sebastes        542
1954    Sebastes        303",
header = TRUE, stringsAsFactors = FALSE)

我使用 data.table 的方法如下。我正在使用 data.table::CJ 生成少数 taxon_name 选项和 5 年序列的笛卡尔连接,然后随机填充 amount

library(data.table)

set.seed(1234)

DT <- CJ(year = seq.int(1950L,1954L,1L),
        taxon_name = c("Gadus morhua","Sebastes","Melanogrammus aeglefinus",
                       "Reinhardtius hippoglossoides","Foo","Bar","Baz"))


DT[, amount := sample.int(100, .N)]
setkey(DT,taxon_name)

print(DT[sample(.N,5)])

#    year                   taxon_name amount
# 1: 1951 Reinhardtius hippoglossoides     25
# 2: 1951                          Baz     99
# 3: 1953                          Baz     13
# 4: 1951                     Sebastes     81
# 5: 1950 Reinhardtius hippoglossoides     97

Top4 <- DT[,.(amount = sum(amount)), by = .(taxon_name)][order(-amount)][1:4,taxon_name]

print(Top4)

# [1] "Sebastes" "Baz" "Melanogrammus aeglefinus" "Gadus morhua"