为什么 map %>% as.data.frame 给出的结果与 map_df 不同?
Why does map %>% as.data.frame give different result than map_df?
我是 R 的新手,正在尝试了解如何使用 map
和 map_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
函数获得第二个输出?
map_df()
似乎按行绑定列表元素(与 map_dfr()
相同),尽管在其 documentation. If you would like to bind by column, use map_dfc()
instead. Note that the output is a tibble in which the use of rownames is discouraged. This document 中没有明确说明在 tibbles 中使用行名的建议方法。
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
- 首先,您使用了
split
而不是 group_split
,这表明您正在创建一个命名列表。
- 其次,在创建命名列表(包含三个项目)后,您将使用
apply
对列表中所有三个项目的第一列取平均值
- 计算平均值后,剩下的结果仍然是一个三项列表,其中一行包含所有四列的平均值。
- 现在区别来了-
- 由于您在第一步中创建了一个命名列表,如果您使用
map_df
或 map_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
因此,列表到数据框的默认绑定是按列的,如果命名了列表,项目名称将用作输出 df 的列名称。另一方面,如果您通过 map_df
或 map_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
希望这是清楚的。
我是 R 的新手,正在尝试了解如何使用 map
和 map_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
函数获得第二个输出?
map_df()
似乎按行绑定列表元素(与 map_dfr()
相同),尽管在其 documentation. If you would like to bind by column, use map_dfc()
instead. Note that the output is a tibble in which the use of rownames is discouraged. This document 中没有明确说明在 tibbles 中使用行名的建议方法。
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
- 首先,您使用了
split
而不是group_split
,这表明您正在创建一个命名列表。 - 其次,在创建命名列表(包含三个项目)后,您将使用
apply
对列表中所有三个项目的第一列取平均值
- 计算平均值后,剩下的结果仍然是一个三项列表,其中一行包含所有四列的平均值。
- 现在区别来了-
- 由于您在第一步中创建了一个命名列表,如果您使用
map_df
或map_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
因此,列表到数据框的默认绑定是按列的,如果命名了列表,项目名称将用作输出 df 的列名称。另一方面,如果您通过 map_df
或 map_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
希望这是清楚的。