【问题标题】:Carrying out a simple dataframe subset with dplyr使用 dplyr 执行一个简单的数据帧子集
【发布时间】:2019-02-05 07:43:36
【问题描述】:

考虑以下数据帧切片:

df = data.frame(locations = c("argentina","brazil","argentina","denmark"),
                score = 1:4,
                row.names = c("a091", "b231", "a234", "d154"))
df

     locations score
a091 argentina     1
b231    brazil     2
a234 argentina     3
d154   denmark     4

sorted = c("a234","d154","a091") #in my real task these strings are provided from an exogenous function

df2 = df[sorted,] #quick and simple subset using rownames

编辑:在这里,我尝试根据sorted 对数据进行子集化和排序 - 抱歉,之前不清楚。所以输出,重要的是:

     locations score
a234 argentina     1
d154   denmark     4
a091 argentina     3

而不是像您从简单的子集操作中得到的那样:

     locations score
a091 argentina     1
a234 argentina     3
d154   denmark     4

我想在 dplyr 中做同样的事情。这是一个不雅的hack:

require(dplyr)    
dt = as_tibble(df)
rownames(dt) = rownames(df)

Warning message:
Setting row names on a tibble is deprecated.

dt2 = dt[sorted,]

我想正确地做,其中行名是数据表中的索引:

dt_proper = as_tibble(x = df,rownames = "index")
dt_proper2 = dt_proper %>% ?some_function(index, sorted)? #what would this be?

dt_proper2

# A tibble: 3 x 3
  index locations score
  <chr> <fct>     <int>
1 a091  argentina     1
2 d154  denmark       4
3 a234  argentina     3

但我终其一生都无法弄清楚如何使用filter 或其他一些 dplyr 函数来做到这一点,并且没有一些复杂的因子转换、重新排序因子水平等。

【问题讨论】:

  • 检查tibble::rownames_to_column()
  • 这似乎允许人们在我上面概述的后两个代码块之间来回转换。是否可以按照我在后一个代码块的结构中描述的那样做? IE。忽略行名 - 我描述的操作可以使用 tibble 中的列来完成吗?
  • 如果您想使用dplyr 做同样的事情,为什么要将数据集更改为tibble?保持原样并执行df %&gt;% filter(rownames(.) %in% sorted)
  • 我不会把它改成 tibble;我在整个数据处理过程中一般都在使用 tibble;我只是想通过与 dataframe 的类似操作来说明我想要的操作。您指定的功能只会过滤;不幸的是,它不会重新排列行。我已更新问题以反映这一点。

标签: r dplyr


【解决方案1】:

喂,

您可以简单地使用 mutate 和 filter 将数据框的 row.names 获取到索引列中,然后过滤到“排序”的向量,并根据向量“排序”对数据框进行排序:

df2 <- df %>% mutate(index=row.names(.)) %>% filter(index %in% sorted)
df2 <- df2[order(match(df2[,"index"], sorted))]

【讨论】:

  • 谢谢;我认为这不会返回我正在寻找的结果,因为它不会像上面的第一个块中的类似操作那样重新排序行。我添加了一个目标输出,希望能让问题更清楚。
【解决方案2】:

我想我已经明白了:

dt_proper2 = dt_proper[match(sorted,dt_proper$index),]

似乎是df[sorted,] 的最短实现。

【讨论】:

    【解决方案3】:

    tidyverse 中的函数(dplyr、tibble 等)是围绕这个概念构建的(据我所知),行只包含属性(列),没有行名/标签/索引。因此,为了对列进行排序,您必须引入一个包含每行排名的新列。

    我这样做的方法是创建另一个包含您的“排序信息”(排序属性,排名)的小标题,并将其内部连接到您的原始小标题。然后我可以按等级对行进行排序。

    library(tidyverse)
    
    # note that I've changed the third column's name to avoid confusion
    df = tibble(
      locations = c("argentina","brazil","argentina","denmark"),
      score = 1:4,
      custom_id = c("a091", "b231", "a234", "d154")
      )
    
    sorted_ids = c("a234","d154","a091")
    
    sorting_info = tibble(
      custom_id = sorted_ids,
      rank = 1:length(sorted_ids)
      )
    
    ordered_ids = df %>%
      inner_join(sorting_info) %>% 
      arrange(rank) %>%
      select(-rank)
    

    【讨论】:

    • 如果这是唯一的方法,那就太可惜了 - 不妨使用不优雅的 hack (rownames(df) = custom_id &gt;&gt;&gt; df[sorted_ids,]) 并接受它。我很惊讶基础 R 中如此简单的操作在 tidyverse 中如此复杂!
    • 对数据帧的工作方式相同,但在某些时候 dplyr 可能会在后台将它们转换为 tibble,因此会删除行名,因此将所有数据保留在列中是必不可少的。
    • 其实这可能是最快的重新创建:dt_proper2 = dt_proper[match(sorted,dt_proper$index),]
    猜你喜欢
    • 1970-01-01
    • 2015-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多