【问题标题】:Take n biggest and lowest values with tidyverse用 tidyverse 取 n 个最大值和最小值
【发布时间】:2020-03-28 22:00:39
【问题描述】:

我想在给定数据帧的情况下获得 k 个最正值和最负值,而不必分别存储它们。目前我正在为 k = 2 执行以下操作:

df %>%
arrange(desc(n)) %>%
top_n(2)

df %>%
arrange(desc(n)) %>%
top_n(-2))

但我想知道是否有更简单的方法来执行此操作而无需存储它们然后 bind_rows 。我想是的,因为这样做真的很方便geom_bars

假设我正在使用任何 tibble,例如:

df <- tibble(x = 1:10, n = 1:10)

我想得到值1,2,9,10

【问题讨论】:

  • 根据您的示例,您的意思是数据框中的最大和最小数字,而不是正数和负数。我认为值得编辑问题以使其清楚。

标签: r tidyverse


【解决方案1】:

我们可以在arrangeing by 'n' 之后使用slice。在这里,我们只调用一次arrange

library(dplyr)
top_n_rows <- 2
df %>% 
    arrange(n) %>%
    slice(sort(c(seq_len(top_n_rows),  n() - seq_len(top_n_rows) + 1)))
# A tibble: 4 x 2
#      x     n
#  <int> <int>
#1     1     1
#2     2     2
#3     9     9
#4    10    10

或者另一个选项是row_number()

df %>%
   arrange(n) %>%
   slice(c(head(row_number(), top_n_rows), tail(row_number(), top_n_rows)))

如果我们只是对前 n 行和后 n 行进行子集化而不考虑要排序的任何列

rbind(head(df, top_n_rows), tail(df, top_n_rows))

row.names

df[c(head(row.names(df), top_n_rows), tail(row.names(df), top_n_rows)),]

【讨论】:

  • 我喜欢第二个!更清晰的imo
  • 是否应该考虑数据帧长度小于2*top_n_rows的一般情况?结果应该是什么?
  • @MarkNeal 这取决于 OP 可能需要什么。如果是完整的data.frame或错误
【解决方案2】:

另一种选择:

library(dplyr)

df %>%
  slice(which(rank(n) %in% 1:2), which(rank(desc(n)) %in% 1:2))

输出:

# A tibble: 4 x 2
      x     n
  <int> <int>
1     1     1
2     2     2
3     9     9
4    10    10

【讨论】:

    【解决方案3】:

    对于正/负值,我遇到了这个解决方案

    df %>%
      group_by(n < 0) %>%
      top_n(2, abs(n)) %>%
      ungroup()
    

    【讨论】:

      【解决方案4】:

      我们可以预先计算我们想要选择的行

      no_rows <- 2
      num <- c(1:no_rows, (nrow(df) - no_rows + 1):nrow(df))
      

      然后我们可以使用slice

      library(dplyr)
      df %>% slice(num)
      
      #      x     n
      #  <int> <int>
      #1     1     1
      #2     2     2
      #3     9     9
      #4    10    10
      

      filter

      df %>% filter(row_number() %in% num)
      

      显然这也适用于直接子集:

      df[num, ]
      

      除了使用top_n时不需要arrange的数据,直接使用即可

      bind_rows(df %>% top_n(no_rows, n), df %>% top_n(-no_rows, n)) %>% arrange_all()
      

      【讨论】:

        猜你喜欢
        • 2018-10-30
        • 1970-01-01
        • 1970-01-01
        • 2020-02-18
        • 1970-01-01
        • 1970-01-01
        • 2023-04-02
        • 1970-01-01
        相关资源
        最近更新 更多