如何更新(分配新值)到存储在列表中的 R 数据帧

How to update (assign new values) to R data frames stored in a list

# sample data
options(stringsAsFactors = FALSE)

set.seed(1)
v1 = stringi::stri_rand_strings(4,3)
v2 = rep("",4)
df1 = data.frame(v1, v2)

set.seed(2)
v1 = stringi::stri_rand_strings(4,3)
v2 = rep("",4)
df2 = data.frame(v1, v2)

df.list = list(df1,df2)
df.list

[[1]]
   v1 v2
1 GNZ   
2 uCt   
3 wed   
4 3CA   

[[2]]
   v1 v2
1 BhZ   
2 Aww   
3 8pT   
4 YYE   

我想以矢量化方式为每个数据帧的每一行分配一个 v1 到 v2 的子字符串,例如,v2 = v1 的第三个字符,得到这个:

> df.list
[[1]]
   v1 v2
1 GNZ  Z
2 uCt  t
3 wed  d
4 3CA  A

[[2]]
   v1 v2
1 BhZ  Z
2 Aww  w
3 8pT  T
4 YYE  E

我知道这个 for 循环有效

for (df in 1:2){
    df.list[[df]]$v2 = substr(df.list[[df]]$v1, 3, 3)
}
df.list

我知道我可以使用 rbind.fill(df.list) 然后设置 $v2 = substr($v1, 3, 3)

我知道我可以在将数据框存储在列表中之前进行子字符串化,但我宁愿一次对所有子字符串进行子字符串化。

我想将数据保存在列表中 b/c 该列表由将在其他代码中使用的字符串索引。 rbind.fill 不保留索引/行名。

我知道这行不通

sapply(df.list, "[[", "v2") <- sapply(df.list, function(x) substr(x$v1, 3,3))

即使右侧标识了正确的子字符串。我意识到左侧的 sapply 是一个输出函数,并不指向目标。但这传达了我正在尝试做的事情的想法。

这也会生成子字符串 sapply(df.list, function(x) {x$v2 <- substr(x$v1,3,3)}),但不会进行赋值。

那么如何指向存储在列表中的每个结构等效数据帧的同一列以向量化方式进行赋值?

使用 lapply 可以让您轻松地对列表中的每个元素应用函数。 这是使用 lapplydplyrmutate 函数的解决方案。

lapply(df.list, function(df) dplyr::mutate(df, v2=substr(v1,3,3)))

使用基础 R 的替代解决方案

lapply(df.list, function(df) data.frame(v1=df$v1, v2=substr(df$v1,3,3)))

lapply(df.list, function(df) {
  df$v2 <- substr(df$v1,3,3)
  return(df)
})