R: Замена значений одного элемента списка значениями второго элемента списка - PullRequest
0 голосов
/ 03 февраля 2019

Я хочу заменить значения одного элемента списка значениями второго элемента списка.В частности,

У меня есть список, содержащий несколько наборов данных. Каждый набор данных имеет 2 переменные Переменные являются факторами n-й элемент второй переменной каждого набора данных необходимо заменить на n-йэлемент первой переменной в каждом наборе данных Кроме того, заменяемое значение должно называться «заменено»
dat1 <- data.frame(names1 =c("a", "b", "c", "f", "x"),values= c("val1_1", "val2_1", "val3_1", "val4_1", "val5_1"))
   dat1$values <- as.factor(dat1$values)
dat2 <- data.frame(names1 =c("a", "b", "f2", "s5", "h"),values= c("val1_2", "val2_2", "val3_2", "val4_2", "val5_2"))
   dat2$values <- as.factor(dat2$values)
list1 <- list(dat1, dat2)

Результатом должен быть тот же список, но только с5-е значение заменено.

[[1]]
     names1  values
1         a  val1_1
2         b  val2_1
3         c  val3_1
4         f  val4_1
5  replaced       x
[[2]]
     names1  values
1         a  val1_2
2         b  val2_2
3        f2  val3_2
4        s5  val4_2
5  replaced       h

Ответы [ 2 ]

0 голосов
/ 03 февраля 2019

Вот один вариант с tidyverse.Пролистайте list с map, slice интересующей строкой (в данном случае это последняя строка, поэтому можно использовать n()), mutate значение столбца и свяжите с исходными даннымибез последнего ряда

library(tidyverse)
map(list1, ~ .x %>% 
               slice(n()) %>%
               mutate(values = names1, names1 = 'replaced') %>% 
               bind_rows(.x %>% slice(-n()), .))
#[[1]]
#    names1 values
#1        a val1_1
#2        b val2_1
#3        c val3_1
#4        f val4_1
#5 replaced      x

#[[2]]
#    names1 values
#1        a val1_2
#2        b val2_2
#3       f2 val3_2
#4       s5 val4_2
#5 replaced      h

Или его можно сделать более компактным с помощью fct_c из forcats.Различные уровни factor могут быть объединены вместе с fct_c для столбца 'values' и 'names1'

library(forcats)
map(list1, ~ .x %>% 
        mutate(values = fct_c(values[-n()], names1[n()]), 
               names1 = fct_c(names1[-n()], factor('replaced'))))

Или с использованием аналогичного подхода с base R, где мы перебираем list с lapply, затем преобразуйте data.frame в matrix, rbind подмножество матрицы, то есть последнюю строку, удаленную со значениями интереса, и преобразуйте в data.frame (по умолчанию stringsAsFactors = TRUE - таконо преобразуется в factor)

lapply(list1,  function(x)  as.data.frame(rbind(as.matrix(x)[-5, ], 
              c('replaced',  as.character(x$names1[5])))))
0 голосов
/ 03 февраля 2019

Подход базового R с использованием lapply, поскольку оба столбца являются факторами, нам нужно сначала добавить новые levels, прежде чем заменять их новыми значениями, в противном случае эти значения будут иметь вид NA с.

n <- 5

lapply(list1, function(x) {
   levels(x$values) <- c(levels(x$values), as.character(x$names1[n]))
   x$values[n] <- x$names1[n]
   levels(x$names1) <- c(levels(x$names1), "replaced")
   x$names1[n] <- "replaced"
   x
})

#[[1]]
#    names1 values
#1        a val1_1
#2        b val2_1
#3        c val3_1
#4        f val4_1
#5 replaced      x

#[[2]]
#    names1 values
#1        a val1_2
#2        b val2_2
#3       f2 val3_2
#4       s5 val4_2
#5 replaced      h

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...