整洁的宇宙(tidyverse)- 将命名向量转换为数据框(data.frame)/ tibble的首选方式

27

我经常使用 tidyverse ,面临的挑战是如何将已命名向量转换为以向量名称为列名的 data.frame/tibble
有没有更加优选/适用于 tidyverse 的方法来做到这一点呢?
编辑:这与以下 GitHub 问题有关:此处此处

所以,我想要:

require(tidyverse)
vec <- c("a" = 1, "b" = 2)

变成这样:

# A tibble: 1 × 2
      a     b
  <dbl> <dbl>
1     1     2

我可以通过以下方式完成这个任务,例如:
vec %>% enframe %>% spread(name, value)
vec %>% t %>% as_tibble

使用案例示例:

require(tidyverse)
require(rvest)
txt <- c('<node a="1" b="2"></node>',
         '<node a="1" c="3"></node>')

txt %>% map(read_xml) %>% map(xml_attrs) %>% map_df(~t(.) %>% as_tibble)

这给出了

# A tibble: 2 × 3
      a     b     c
  <chr> <chr> <chr>
1     1     2  <NA>
2     1  <NA>     3

你认为你所做的事情缺少什么,如果有的话? - shayaa
2
我也曾经问过自己同样的问题,因为bind_rows不能代替map_df(~t(.) %>% as_tibble)。所以,到目前为止,我会先转置,然后将其转换为一个数据框,使字符串保持字符形式(而不是因子),最后再将结果绑定在一起。然而,这个常见任务的快捷方式会很方便。 - lukeA
1
@lukeA,我认为bind_rows已经更新,现在可以按照你想要的方式工作。 - markdly
5个回答

30
现在可以直接使用bind_rows(在dplyr 0.7.0中引入)来支持此操作:

library(tidyverse)) 
vec <- c("a" = 1, "b" = 2)

bind_rows(vec)
#> # A tibble: 1 x 2
#>       a     b
#>   <dbl> <dbl>
#> 1     1     2

这段引用来自https://cran.r-project.org/web/packages/dplyr/news.html,解释了改变的原因:

bind_rows()bind_cols() 现在可以接受向量作为参数。前者将其视为行,后者将其视为列。行需要内部名称,例如 c(col1 = 1, col2 = 2),而列需要外部名称:col1 = c(1, 2)。列表仍然被视为数据帧,但可以用 !!! 显式地拼接,例如 bind_rows(!!! x) (#1676)。

这个改变意味着用例示例中的以下行: txt %>% map(read_xml) %>% map(xml_attrs) %>% map_df(~t(.) %>% as_tibble) 可以重写为: txt %>% map(read_xml) %>% map(xml_attrs) %>% map_df(bind_rows) 它也等同于: txt %>% map(read_xml) %>% map(xml_attrs) %>% { bind_rows(!!! .) } 不同方法的等效性在以下示例中进行演示:
library(tidyverse)
library(rvest)

txt <- c('<node a="1" b="2"></node>',
         '<node a="1" c="3"></node>')

temp <- txt %>% map(read_xml) %>% map(xml_attrs)

# x, y, and z are identical
x <- temp %>% map_df(~t(.) %>% as_tibble)
y <- temp %>% map_df(bind_rows)
z <- bind_rows(!!! temp)

identical(x, y)
#> [1] TRUE
identical(y, z)
#> [1] TRUE

z
#> # A tibble: 2 x 3
#>       a     b     c
#>   <chr> <chr> <chr>
#> 1     1     2  <NA>
#> 2     1  <NA>     3

我对你引用的设置“内部名称”和“外部名称”的区别有些困惑。请参见我的问题:https://stackoverflow.com/q/67010860/5535152 - Emy

7
惯用的方法是在 tibble() 调用中使用 !!! 来拼接向量,这样命名的向量元素就会成为列定义:
library(tibble)
vec <- c("a" = 1, "b" = 2)
tibble(!!!vec)
#> # A tibble: 1 x 2
#>       a     b
#>   <dbl> <dbl>
#> 1     1     2

reprex package (v0.3.0) 于2019年09月14日创建


1
这对我有效: c("a" = 1, "b" = 2) %>% t() %>% tbl_df()

1
有趣的是,您可以使用as_tibble()方法来对列表进行一次性转换。请注意,这不是最佳实践,因为这不是一个导出的方法。
tibble:::as_tibble.list(vec)

1
as_tibble(as.list(c(a=1, b=2)))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接