问题:
如何修改已建立列表中的元素并将其重新分配回列表中的相同索引/位置?
设置和示例
首先,这是一个数据框,我将其按组分解为列表:
library(tidyverse) # Not absolutely required, but I'm working this way.
df <- tibble(A = rep(paste("Group", c(1:3)),3),
B = seq(1, 18, 2),
C = (1:9))
lst <- df %>%
group_by(A) %>%
group_split()
数据框和结果列表应如下所示:
> df
# A tibble: 9 × 3
A B C
<chr> <dbl> <int>
1 Group 1 1 1
2 Group 2 3 2
3 Group 3 5 3
4 Group 1 7 4
5 Group 2 9 5
6 Group 3 11 6
7 Group 1 13 7
8 Group 2 15 8
9 Group 3 17 9
> lst
<list_of<
tbl_df<
A: character
B: double
C: integer
>
>[3]>
[[1]]
# A tibble: 3 × 3
A B C
<chr> <dbl> <int>
1 Group 1 1 1
2 Group 1 7 4
3 Group 1 13 7
[[2]]
# A tibble: 3 × 3
A B C
<chr> <dbl> <int>
1 Group 2 3 2
2 Group 2 9 5
3 Group 2 15 8
[[3]]
# A tibble: 3 × 3
A B C
<chr> <dbl> <int>
1 Group 3 5 3
2 Group 3 11 6
3 Group 3 17 9
这就是问题...
由于与此处无关的原因,我需要根据组对列表中的每个子数据帧进行不同的处理。我想我可以像下面这样在循环中应用修改,将列表结构保留在适当的位置。
for (j in 1:3){
lst[[j]] <- lst[[j]] %>%
mutate(D = B * C)
}
...但这会引发此错误:
Error in `[[<-`:
! Can't convert from `value` <tbl_df<
A: character
B: double
C: integer
D: double
>> to <tbl_df<
A: character
B: double
C: integer
>> due to loss of precision.
我知道分配回列表是问题所在,因为我可以成功地做到这一点:
df2 <- NULL
df_final <- NULL
for (j in 1:3){
df2 <- lst[[j]] %>%
mutate(D = B * C)
df_final <- rbind(df_final, df2)
}
df_final
...它返回一个数据帧,我可以像开始一样将其分解。
> df_final
# A tibble: 9 × 4
A B C D
<chr> <dbl> <int> <dbl>
1 Group 1 1 1 1
2 Group 1 7 4 28
3 Group 1 13 7 91
4 Group 2 3 2 6
5 Group 2 9 5 45
6 Group 2 15 8 120
7 Group 3 5 3 15
8 Group 3 11 6 66
9 Group 3 17 9 153
...但我觉得我错过了如何将列表“就地”分配为上面的一些细微差别,而且我不理解错误消息。关于分配到使 lst[[j]] <- lst[[j]] %>% <ANY MODIFICATION>
的列表,我缺少什么失败?
最佳答案
group_split()
的结果不是一个简单的列表,但对其中的表有一些跟踪,以防止仅修改一项。
您可以使用 lst <- as.list(lst)
来避免这种情况.
library(dplyr) # Not absolutely required, but I'm working this way.
df <- tibble(A = rep(paste("Group", c(1:3)),3),
B = seq(1, 18, 2),
C = (1:9))
lst <- df %>%
group_by(A) %>%
group_split()
for (j in 1:3){
lst[[j]] <- lst[[j]] %>%
mutate(D = B * C)
}
#> Error in `[[<-`:
#> ! Can't convert from `value` <tbl_df<
#> A: character
#> B: double
#> C: integer
#> D: double
#> >> to <tbl_df<
#> A: character
#> B: double
#> C: integer
#> >> due to loss of precision.
lst <- as.list(lst)
for (j in 1:3){
lst[[j]] <- lst[[j]] %>%
mutate(D = B * C)
} # OK
df_final <- bind_rows(lst)
df_final
#> # A tibble: 9 × 4
#> A B C D
#> <chr> <dbl> <int> <dbl>
#> 1 Group 1 1 1 1
#> 2 Group 1 7 4 28
#> 3 Group 1 13 7 91
#> 4 Group 2 3 2 6
#> 5 Group 2 9 5 45
#> 6 Group 2 15 8 120
#> 7 Group 3 5 3 15
#> 8 Group 3 11 6 66
#> 9 Group 3 17 9 153
或
您可以使用map
将函数映射到列表中的每个项目。
lst <- map(lst, ~ mutate(., D=B*C))
df_final <- bind_rows(lst)
df_final
关于r - 在 R 中,如何使用索引修改/重新分配列表元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74133220/