【问题标题】:Why does map %>% as.data.frame give different result than map_df?为什么 map %>% as.data.frame 给出的结果与 map_df 不同?
【发布时间】:2021-06-03 01:41:59
【问题描述】:

我是 R 新手,想了解如何使用 mapmap_df。考虑以下几点:

iris %>% split(.$Species) %>% map_df(function (x) apply(x[, 1:4], 2, mean))

比较

iris %>% split(.$Species) %>% map(function (x) apply(x[, 1:4], 2, mean)) %>% as.data.frame

前者给出以下输出:

  Sepal.Length Sepal.Width Petal.Length Petal.Width
         <dbl>       <dbl>        <dbl>       <dbl>
1         5.01        3.43         1.46       0.246
2         5.94        2.77         4.26       1.33
3         6.59        2.97         5.55       2.03

后者给出:

             setosa versicolor virginica
Sepal.Length  5.006      5.936     6.588
Sepal.Width   3.428      2.770     2.974
Petal.Length  1.462      4.260     5.552
Petal.Width   0.246      1.326     2.026

我的问题是:为什么?我希望这两个命令给出相同的输出。如何使用map_df 函数获得第二个输出?

【问题讨论】:

  • 你为什么不能做iris %&gt;%group_by(Species)%&gt;%summarise_all(mean)
  • 对不起,我想特别使用map_df——我应该说清楚的。

标签: r tidyverse purrr


【解决方案1】:

map_df() 似乎按行绑定列表元素(与map_dfr() 相同),尽管在其documentation 中没有明确说明。如果您想按列绑定,请改用map_dfc()。请注意,输出是一个不鼓励使用行名的 tibble。这个document 建议了在小标题中使用行名的方法。

iris %>% 
  split(.$Species) %>% 
  map_dfc(function (x) apply(x[, 1:4], 2, mean))

# # A tibble: 4 x 3
#   setosa versicolor virginica
#    <dbl>      <dbl>     <dbl>
# 1  5.01        5.94      6.59
# 2  3.43        2.77      2.97
# 3  1.46        4.26      5.55
# 4  0.246       1.33      2.03

【讨论】:

  • 你是对的,运行 iris %>% split(.$Species) %>% map(function (x) apply(x[, 1:4], 2, mean)) %>% bind_cols() 给出与 map_df 相同的输出。
  • 你可以看到这个命令的输出实际上和iris %&gt;% split(.$Species) %&gt;% map_df(function (x) apply(x[, 1:4], 2, mean))不一样,这是造成混乱的原因
  • 没关系,只是它的舍入方式不同!谢谢!
【解决方案2】:
  • 首先,您使用了split 而不是group_split,这表明您正在创建一个命名列表。
  • 其次,在您创建了一个命名列表(包含三个项目)之后,您将使用apply 对列表中所有三个项目的第一列进行平均处理
  • 平均计算之后,剩下的结果仍然是一个三项列表,其中一行包含所有四列的平均值。
  • 现在区别来了——
    • 由于您在第一步中创建了一个命名列表,如果您使用map_dfmap_dfr(两者的结果相同),map 函数只需行绑定输出。
    • 但是,使用 map 会将列表保留为列表(已命名),as.data.frame 会按列绑定。
library(tidyverse)
#1st case
iris %>% split(.$Species) %>% map_dfr(function (x) apply(x[, 1:4], 2, mean))
#> # A tibble: 3 x 4
#>   Sepal.Length Sepal.Width Petal.Length Petal.Width
#>          <dbl>       <dbl>        <dbl>       <dbl>
#> 1         5.01        3.43         1.46       0.246
#> 2         5.94        2.77         4.26       1.33 
#> 3         6.59        2.97         5.55       2.03

#OR
iris %>% split(.$Species) %>% map_df(function (x) apply(x[, 1:4], 2, mean))
#> # A tibble: 3 x 4
#>   Sepal.Length Sepal.Width Petal.Length Petal.Width
#>          <dbl>       <dbl>        <dbl>       <dbl>
#> 1         5.01        3.43         1.46       0.246
#> 2         5.94        2.77         4.26       1.33 
#> 3         6.59        2.97         5.55       2.03

#2nd case
iris %>% split(.$Species) %>% map(function (x) apply(x[, 1:4], 2, mean)) %>% as.data.frame
#>              setosa versicolor virginica
#> Sepal.Length  5.006      5.936     6.588
#> Sepal.Width   3.428      2.770     2.974
#> Petal.Length  1.462      4.260     5.552
#> Petal.Width   0.246      1.326     2.026

#OR (with a slight difference of dropping row names)
iris %>% split(.$Species) %>% map_dfc(function (x) apply(x[, 1:4], 2, mean))
#> # A tibble: 4 x 3
#>   setosa versicolor virginica
#>    <dbl>      <dbl>     <dbl>
#> 1  5.01        5.94      6.59
#> 2  3.43        2.77      2.97
#> 3  1.46        4.26      5.55
#> 4  0.246       1.33      2.03

#If group_split would have been used instead
iris %>% group_split(Species) %>% map(function (x) apply(x[, 1:4], 2, mean)) %>% as.data.frame
#>              c.Sepal.Length...5.006..Sepal.Width...3.428..Petal.Length...1.462..
#> Sepal.Length                                                               5.006
#> Sepal.Width                                                                3.428
#> Petal.Length                                                               1.462
#> Petal.Width                                                                0.246
#>              c.Sepal.Length...5.936..Sepal.Width...2.77..Petal.Length...4.26..
#> Sepal.Length                                                             5.936
#> Sepal.Width                                                              2.770
#> Petal.Length                                                             4.260
#> Petal.Width                                                              1.326
#>              c.Sepal.Length...6.588..Sepal.Width...2.974..Petal.Length...5.552..
#> Sepal.Length                                                               6.588
#> Sepal.Width                                                                2.974
#> Petal.Length                                                               5.552
#> Petal.Width                                                                2.026

#OR
iris %>% group_split(Species) %>% map_dfc(function (x) apply(x[, 1:4], 2, mean))
#> New names:
#> * NA -> ...1
#> * NA -> ...2
#> * NA -> ...3
#> # A tibble: 4 x 3
#>    ...1  ...2  ...3
#>   <dbl> <dbl> <dbl>
#> 1 5.01   5.94  6.59
#> 2 3.43   2.77  2.97
#> 3 1.46   4.26  5.55
#> 4 0.246  1.33  2.03

因此,list 到数据框的默认绑定是按列绑定的,如果 list 被命名,项目名称将用作输出 df 的列名称。另一方面,如果您通过map_dfmap_dfr 发出特定命令,则列表项将按行绑定,因此不需要列表项的名称。

iris %>% group_split(Species) %>% map_dfr(function (x) apply(x[, 1:4], 2, mean))

# A tibble: 3 x 4
  Sepal.Length Sepal.Width Petal.Length Petal.Width
         <dbl>       <dbl>        <dbl>       <dbl>
1         5.01        3.43         1.46       0.246
2         5.94        2.77         4.26       1.33 
3         6.59        2.97         5.55       2.03 

希望这很清楚。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多