使用 lapply 与 R 变异时的输入大小问题
Input size issue when using lapply to mutate with R
我有 mylist
,其中包含 2 个列表,示例数据如下。
使用 class(mylist[[1]])
得到 "grouped_df"
"tbl_df"
"tbl"
"data.frame"
[[1]]
# A tibble: 2 x 5
# Groups: Year, Commodity [2]
Year Commodity Commodity.Code value1_k value2_k
<int> <chr> <int> <dbl> <dbl>
1 2010 A 721 100 100
2 2010 B 792 200 200
[[2]]
# A tibble: 2 x 5
# Groups: Year, Commodity [2]
Year Commodity Commodity.Code value1_m value2_m
<int> <chr> <int> <dbl> <dbl>
1 2010 A 721 100 100
2 2010 B 792 200 200
我尝试使用 mutate()
向两个小标题添加一个新列 div
,其值是通过使用以下代码将第 4 列除以第 5 列得出的:
mylist2 <- lapply(1:2, function(i){
mylist[[i]] %>% mutate(div=.[[4]] /.[[5]])
})
这将引发以下错误:
Error: Problem with `mutate()` input `div`.
x Input `div` can't be recycled to size 1.
i Input `div` is `.[[4]]/.[[5]]`.
i Input `div` must be size 1, not 2.
i The error occurred in group 1: Year = 2010, Commodity = "A".
正在尝试重现问题
我尝试用数据集 cars
重现问题,
但这次代码有效。
cars1 <- cars +1
cars2 <- cars +2
cars_all <- list(cars1,cars2)
lapply(1:2, function(i){
cars_all[[i]] %>% mutate(div = .[[1]] / .[[2]])
})
比较两个列表列表,我注意到 类 是不同的,即
class(cars_all[[1]])
给出 "data.frame"
class(mylist[[1]])
给出 "grouped_df"
"tbl_df"
"tbl"
"data.frame"
但是,我尝试在应用 lapply 之前使用 as.data.frame
,但问题仍然存在。
我使用lapply
因为实际的mylist包含更多列表;
我使用索引形式而不是列名来执行除法,因为列名在列表中是不同的(并且很重要,需要保留)。
我的目标是如前所述添加额外的列,其值是通过除法得出的。
如果有更好的方法可以实现这一点,请告诉我。
非常感谢您的帮助。
问题似乎是由分组引起的。这是一个可重现的例子:
library(tidyverse)
df1 <- tibble::tribble(
~Year, ~Commodity, ~Commodity.Code, ~value1_k, ~value2_k,
2010, "A", 721, 100, 100,
2010, "B", 792, 200, 200
) %>%
group_by(Year, Commodity)
df2 <- tibble::tribble(
~Year, ~Commodity, ~Commodity.Code, ~value1_k, ~value2_k,
2011, "C", 7242, 111, 123,
2011, "D", 7421, 222, 234
) %>%
group_by(Year, Commodity)
str(df1)
#>grouped_df[,5] [2 × 5] (S3: grouped_df/tbl_df/tbl/data.frame)
str(df2)
#>grouped_df[,5] [2 × 5] (S3: grouped_df/tbl_df/tbl/data.frame)
mylist <- list(df1, df2)
mylist2 <- lapply(1:2, function(i){
mylist[[i]] %>% mutate(div=.[[4]] /.[[5]])
})
#>Error: Problem with `mutate()` input `div`.
#>x Input `div` can't be recycled to size 1.
#>ℹ Input `div` is `.[[4]]/.[[5]]`.
#>ℹ Input `div` must be size 1, not 2.
#>ℹ The error occurred in group 1: Year = 2010, Commodity = "A".
mylist2 <- lapply(1:2, function(i){
mylist[[i]] %>% ungroup() %>% mutate(div=.[[4]] /.[[5]])
})
mylist2
#>[[1]]
#> A tibble: 2 x 6
#> Year Commodity Commodity.Code value1_k value2_k div
#> <dbl> <chr> <dbl> <dbl> <dbl> <dbl>
#>1 2010 A 721 100 100 1
#>2 2010 B 792 200 200 1
#>[[2]]
#> A tibble: 2 x 6
#> Year Commodity Commodity.Code value1_k value2_k div
#> <dbl> <chr> <dbl> <dbl> <dbl> <dbl>
#>1 2011 C 7242 111 123 0.902
#>2 2011 D 7421 222 234 0.949
这对您的 'real' 数据有效吗?
我有 mylist
,其中包含 2 个列表,示例数据如下。
使用 class(mylist[[1]])
得到 "grouped_df"
"tbl_df"
"tbl"
"data.frame"
[[1]]
# A tibble: 2 x 5
# Groups: Year, Commodity [2]
Year Commodity Commodity.Code value1_k value2_k
<int> <chr> <int> <dbl> <dbl>
1 2010 A 721 100 100
2 2010 B 792 200 200
[[2]]
# A tibble: 2 x 5
# Groups: Year, Commodity [2]
Year Commodity Commodity.Code value1_m value2_m
<int> <chr> <int> <dbl> <dbl>
1 2010 A 721 100 100
2 2010 B 792 200 200
我尝试使用 mutate()
向两个小标题添加一个新列 div
,其值是通过使用以下代码将第 4 列除以第 5 列得出的:
mylist2 <- lapply(1:2, function(i){
mylist[[i]] %>% mutate(div=.[[4]] /.[[5]])
})
这将引发以下错误:
Error: Problem with `mutate()` input `div`.
x Input `div` can't be recycled to size 1.
i Input `div` is `.[[4]]/.[[5]]`.
i Input `div` must be size 1, not 2.
i The error occurred in group 1: Year = 2010, Commodity = "A".
正在尝试重现问题
我尝试用数据集 cars
重现问题,
但这次代码有效。
cars1 <- cars +1
cars2 <- cars +2
cars_all <- list(cars1,cars2)
lapply(1:2, function(i){
cars_all[[i]] %>% mutate(div = .[[1]] / .[[2]])
})
比较两个列表列表,我注意到 类 是不同的,即
class(cars_all[[1]])
给出"data.frame"
class(mylist[[1]])
给出"grouped_df"
"tbl_df"
"tbl"
"data.frame"
但是,我尝试在应用 lapply 之前使用 as.data.frame
,但问题仍然存在。
我使用lapply
因为实际的mylist包含更多列表;
我使用索引形式而不是列名来执行除法,因为列名在列表中是不同的(并且很重要,需要保留)。
我的目标是如前所述添加额外的列,其值是通过除法得出的。
如果有更好的方法可以实现这一点,请告诉我。
非常感谢您的帮助。
问题似乎是由分组引起的。这是一个可重现的例子:
library(tidyverse)
df1 <- tibble::tribble(
~Year, ~Commodity, ~Commodity.Code, ~value1_k, ~value2_k,
2010, "A", 721, 100, 100,
2010, "B", 792, 200, 200
) %>%
group_by(Year, Commodity)
df2 <- tibble::tribble(
~Year, ~Commodity, ~Commodity.Code, ~value1_k, ~value2_k,
2011, "C", 7242, 111, 123,
2011, "D", 7421, 222, 234
) %>%
group_by(Year, Commodity)
str(df1)
#>grouped_df[,5] [2 × 5] (S3: grouped_df/tbl_df/tbl/data.frame)
str(df2)
#>grouped_df[,5] [2 × 5] (S3: grouped_df/tbl_df/tbl/data.frame)
mylist <- list(df1, df2)
mylist2 <- lapply(1:2, function(i){
mylist[[i]] %>% mutate(div=.[[4]] /.[[5]])
})
#>Error: Problem with `mutate()` input `div`.
#>x Input `div` can't be recycled to size 1.
#>ℹ Input `div` is `.[[4]]/.[[5]]`.
#>ℹ Input `div` must be size 1, not 2.
#>ℹ The error occurred in group 1: Year = 2010, Commodity = "A".
mylist2 <- lapply(1:2, function(i){
mylist[[i]] %>% ungroup() %>% mutate(div=.[[4]] /.[[5]])
})
mylist2
#>[[1]]
#> A tibble: 2 x 6
#> Year Commodity Commodity.Code value1_k value2_k div
#> <dbl> <chr> <dbl> <dbl> <dbl> <dbl>
#>1 2010 A 721 100 100 1
#>2 2010 B 792 200 200 1
#>[[2]]
#> A tibble: 2 x 6
#> Year Commodity Commodity.Code value1_k value2_k div
#> <dbl> <chr> <dbl> <dbl> <dbl> <dbl>
#>1 2011 C 7242 111 123 0.902
#>2 2011 D 7421 222 234 0.949
这对您的 'real' 数据有效吗?