Как обновить (присвоить новые значения) фреймам данных R, хранящимся в списке

# 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)

Я знаю, что мог бы подстроку перед сохранением фрейма данных в списке, но я бы предпочел подстроку сразу.

Я хотел бы сохранить данные в списке, потому что список индексируется строкой, которая будет использоваться в другом коде. 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)}), но присваивание не выполняется.

Итак, как мне указать один и тот же столбец каждого структурно эквивалентного фрейма данных, хранящегося в списке, чтобы выполнить назначение векторизованным образом?


person LWRMS    schedule 02.09.2016    source источник


Ответы (1)


Использование lapply позволяет легко применять функции к каждому элементу списка. Вот решение, использующее функцию lapply и dplyr mutate.

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)
})
person Adam Spannbauer    schedule 02.09.2016
comment
Вы также можете использовать transform в базе R по аналогии с dplyr::mutate - lapply(df.list, transform, v2=substr(v1,3,3) ) - person thelatemail; 02.09.2016
comment
@thelatemailМне нравится эта идея, но предупреждение в документации transform() относится к моему случаю - person LWRMS; 02.09.2016
comment
@Adam Spannbauer, третий вариант, который вы, к счастью, добавили в более позднем редактировании, является лучшим для моей реальной ситуации, поскольку в моем df.list есть дополнительные столбцы. Это очень похоже на одну из моих попыток, хотя я пропустил return(). Очень хорошие альтернативы, которые учат. Я нашел mutate_all, хотя в документации указано, что он будет объявлен устаревшим. - person LWRMS; 02.09.2016