Сравнение содержимого нескольких фреймов данных в R - PullRequest
0 голосов
/ 28 мая 2018

В этом сценарии у меня несколько фреймов данных (~ 100, числа могут отличаться), но все они имеют одинаковый размер.Они в основном индикаторы, и мне нужно пересечь их все.См. Следующий код:

df1 <- data.frame(col1=c("a","b","c","d"),col2=c(NA,NA,NA,NA),col3=c(NA,"X",NA,"X"),col4=c("X",NA,NA,"X"))
df2 <- data.frame(col1=c("a","b","c","d"),col2=c("X","X",NA,NA),col3=c(NA,NA,NA,"X"),col4=c(NA,NA,NA,NA))
df3 <- data.frame(col1=c("a","b","c","d"),col2=c(NA,NA,"X",NA),col3=c(NA,NA,NA,NA),col4=c(NA,"X",NA,NA))

Мне нужно создать кадр выходных данных, который будет содержать X, если хотя бы один кадр данных содержал X в этой ячейке:

output <- data.frame(col1=c("a","b","c","d"),col2=c("X","X","X",NA),col3=c(NA,"X",NA,"X"),col4=c("X","X",NA,"X"))

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

Ответы [ 3 ]

0 голосов
/ 28 мая 2018

Скажем, мы начинаем с пустого df, столбцы которого мы будем заполнять:

out <- data.frame(col1=c("a","b","c","d"), col2=NA, col3=NA, col4=NA)

Вот один способ, которым вы можете построить один столбец с желаемым свойством:

out$col2 <- sapply(1:nrow(out), function(r){
  ifelse(sum(!is.na(c(df1$col2[r], df2$col2[r], df3$col2[r]))) == 0, NA, "X")
})

Такабстрагируясь от столбца, мы могли бы написать такую ​​функцию:

make_output_column <- function(cname){
  sapply(1:nrow(out), function(r){
    values <- c(df1[[cname]][r], df2[[cname]][r], df3[[cname]][r])
    ifelse(sum(!is.na(values)) == 0, NA, "X")
  })
}

и затем применить ее ко всем столбцам, которые мы хотим построить, чтобы создать желаемый результат:

cols <- c("col2", "col3", "col4")
out[, cols] <- lapply(cols, make_output_column)

## col1 col2 col3 col4
##    a    X <NA>    X
##    b    X    X    X
##    c    X <NA> <NA>
##    d <NA>    X    X
0 голосов
/ 28 мая 2018

Вот техника с do.call и pmax

# put your data.frames into a list
myList <- mget(ls(pattern="df\\d"))

См. Мой ответ на этот пост для более подробной информации по этой строке.

cbind(myList[[1]][1], do.call(function(...) pmax(..., na.rm=TRUE),
                              lapply(myList, "==", "X"))[, 2:4])
  col1 col2 col3 col4
1    a    1   NA    1
2    b    1    1    1
3    c    1   NA   NA
4    d   NA    1    1

Здесь myList[[1]][1] извлекает первый столбец из одного из data.frames в списке, чтобы вернуть data.frame с одним столбцом.Вы можете эквивалентно использовать df[1].lapply(myList, "==", "X") пробегает список data.frames и возвращает значения TRUE и FALSE, если X включает ячейку в данные.Затем do.call использует pmax, чтобы вернуть максимальное значение каждой ячейки для списка ИСТИНА, ЛОЖЬ и НС.

Если очень важно иметь "X" вместо 1, то следуйте этому с

dat[dat == 1] <- "X"
0 голосов
/ 28 мая 2018

Как то так?

    dfs <- list(df1, df2, df3)
    index <- lapply(dfs, function(x) apply(x[,2:4], 1, function(y) all(is.na(y))))
    output2 <- list()
    for(i in 1:length(dfs)){
      output2[[i]] <- dfs[[i]][!index[[i]],]
    }
    output <- do.call(rbind, output)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...