Назначение класса столбца data.frame из другого data.frame r

Имею список data.frames sampleList. Каждый data.frame в этом list немного отличается с точки зрения столбцов и их порядка.

Еще у меня есть еще один data.framerefData1, который я хотел бы использовать в качестве модели для остальных с точки зрения класса колонки с такими же названиями.

Другими словами, я хотел бы, чтобы sampleList был обновлен, и все совпадающие столбцы с refData1 должны изменить свой класс и отражать тип класса в refData1 для соответствующего столбца. Столбцы, которые не совпадают, должны оставаться в прежнем виде. Обратите внимание, что refData1 также содержит столбец, которого нет ни в одном из data.frames в списке. Спасибо.

sampleData1 <- data.frame(id = 1:10, 
                          gender = as.factor(sample(c("Male", "Female"), 
                                                    10, replace = TRUE)),
                          age = as.character(rnorm(10, 40, 10)),
                          height = as.character(rnorm(10,170,5)))
sampleData2 <- data.frame(weight = as.character(rnorm(10,80,5)),
                          gender = sample(c("Male", "Female"), 
                                          10, replace = TRUE),
                          id = 11:20, 
                          age = rnorm(10, 44, 10))
sampleData3 <- data.frame(id = as.factor(21:30), 
                          age = as.character(rnorm(10, 36, 10)),
                          gender = sample(c("Male", "Female"), 10, 
                                          replace = TRUE),
                          score = as.character(rnorm(10,20,2)))
sampleList <- list(sampleData1,sampleData2,sampleData3)

refData1 <- data.frame(id = 1:10, # numeric
                       gender1 = as.character(sample(c("Male", "Female"), 
                                                     10, replace = TRUE)),
                       agen = rnorm(10, 40, 10), # numeric
                       height = rnorm(10,170,5), # numeric
                       weight = rnorm(10,80,5),  # numeric
                       other = as.factor(sample(c("a", "b","c"), 
                                                10, replace = TRUE)))

Я получаю эту ошибку при компиляции вашего кода: «Ошибка в as.factor (id = 21:30): неиспользуемый аргумент (id = 21:30)»

BIM 10.08.2018 15:39

Извините, я исправил это.

MIH 10.08.2018 15:40
2
2
230
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Мы перебираем «sampleList», получаем столбцы intersecting с «refData1», устанавливаем class в data.frame с помощью столбцов «refData1».

sampleListN <- lapply(sampleList, function(x) {
        nm1 <- intersect(names(x), names(refData1))
        x[nm1] <- Map(function(u, v) {class(u) <- class(v)
                               u},
                       x[nm1], refData1[nm1])
         x})

Как упоминалось в @ mt1022, если мы будем следовать логике, то преобразование столбцов factor напрямую в integer может создать проблемы, поскольку мы неверные значения, то есть целые значения хранения вместо фактических значений. Судя по данным, нам даже не нужно сравнивать с refData1. Мы можем сделать это автоматически с помощью type.convert.

lapply(sampleList, function(x) {
       nm1 <- intersect(names(x), names(refData1))
       x[nm1] <- lapply(x[nm1], function(x)
             type.convert(as.character(x), as.is = TRUE))
       x})

Прекрасно работает - спасибо @akrun! Еще один вопрос, если можно - теперь, как мне взять sampleListN и слить в один большой data.frame, но только для тех столбцов, которые появляются в refData1?

MIH 10.08.2018 15:44

@MIH Если это базовый R, то слияние Reduce(function(...) merge(..., by = columnsofinterest), c(refData1, sampleListN)) неясно, потому что некоторые столбцы для refData1 являются непрерывными

akrun 10.08.2018 15:46

Будьте осторожны при преобразовании множителя в числовые типы. Иногда требуется сначала преобразование в символьный тип. В этом примере идентификатор третьего data.frame становится 1:10, а не 21:30.

mt1022 10.08.2018 15:54

True @ mt1022 - должен ли я преобразовать все факторы в символы в списке, если имя столбца совпадает с одним в refData1, или его можно как-то сжать до аккуратного фрагмента кода, выполненного @akrun?

MIH 10.08.2018 15:58

@akrun, к сожалению, ваш фрагмент кода с Reduce () не работает, появляется следующая ошибка: Error in fix.by(by.x, x) : 'by' must specify uniquely valid columns. У меня все определено, включая columnsofinterest

MIH 10.08.2018 15:59

@MIH Я имел в виду columnsofinterest как объект, определенный

akrun 10.08.2018 16:02

Я определил columnsofinterest <- colnames(refData1).

MIH 10.08.2018 16:04

@MIH Но не каждый столбец в refData1 находится в другом наборе данных, верно. Возможно вам понадобится intersect(colnames(refData1), names(sampledata1)) и т. д.

akrun 10.08.2018 16:05

Я просто поступаю так (извините, но я не знаком с ... в функциях, я обычно делаю это по старинке. df.merged <- Reduce(function(...) merge(..., by = columnsofinterest), c(refData1, sampleListN)). Спасибо.

MIH 10.08.2018 16:05

Собственно, удалось это сделать с помощью библиотеки plyrldply(sampleListN,data.frame), тогда я просто оставлю те столбцы, которые мне нужны. Большое спасибо @akrun!

MIH 10.08.2018 16:10

@ Что вам нужно, так это out <- refData1; for(i in seq_along(sampleList)) out <- merge(out, sampleList[[i]], by = intersect(names(out), names(sampleList[[i]]))) Но, к сожалению, нет строк, соответствующих вашему состоянию

akrun 10.08.2018 16:11

Другие вопросы по теме