Объединить столбец, чтобы удалить NA
У меня есть несколько столбцов в R, и для каждой строки будет только значение в одном из них, остальные будут NA. Я хочу объединить их в один столбец со значением не-NA. Кто-нибудь знает простой способ сделать это. Например, я мог бы иметь следующее:
data <- data.frame('a' = c('A','B','C','D','E'),
'x' = c(1,2,NA,NA,NA),
'y' = c(NA,NA,3,NA,NA),
'z' = c(NA,NA,NA,4,5))
Так что я бы
'a' 'x' 'y' 'z'
A 1 NA NA
B 2 NA NA
C NA 3 NA
D NA NA 4
E NA NA 5
И я бы заполучил
'a' 'mycol'
A 1
B 2
C 3
D 4
E 5
Имена столбцов, содержащих NA, изменяются в зависимости от кода, ранее в запросе, поэтому я не смогу явно назвать имена столбцов, но у меня есть имена столбцов столбцов, которые содержат NA, сохраненные в виде вектора, например, в этом примере cols <- c('x','y','z')
поэтому можно вызывать столбцы используя data[, cols]
,
Любая помощь будет оценена.
Спасибо
8 ответов
Ты можешь использовать unlist
превратить столбцы в один вектор. После этого, na.omit
может быть использован для удаления NA
s.
cbind(data[1], mycol = na.omit(unlist(data[-1])))
a mycol
x1 A 1
x2 B 2
y3 C 3
z4 D 4
z5 E 5
dplyr::coalesce
Решение на основе может быть как:
data %>% mutate(mycol = coalesce(x,y,z)) %>%
select(a, mycol)
# a mycol
# 1 A 1
# 2 B 2
# 3 C 3
# 4 D 4
# 5 E 5
Данные
data <- data.frame('a' = c('A','B','C','D','E'),
'x' = c(1,2,NA,NA,NA),
'y' = c(NA,NA,3,NA,NA),
'z' = c(NA,NA,NA,4,5))
Вот более общее (но даже более простое) решение, которое распространяется на все типы столбцов (факторы, символы и т. Д.) С неупорядоченными NA. Стратегия состоит в том, чтобы просто объединить значения не-NA других столбцов в объединенный столбец, используя is.na
для индексации:
data$m = data$x # your new merged column start with x
data$m[!is.na(data$y)] = data$y[!is.na(data$y)] # merge with y
data$m[!is.na(data$z)] = data$z[!is.na(data$z)] # merge with z
> data
a x y z m
1 A 1 NA NA 1
2 B 2 NA NA 2
3 C NA 3 NA 3
4 D NA NA 4 4
5 E NA NA 5 5
Обратите внимание, что это перезапишет существующие значения в m
если в одной строке несколько значений не-NA Если у вас есть много столбцов, вы можете автоматизировать это, циклически colnames(data)
,
Я хотел бы использовать rowSums()
с na.rm = TRUE
аргумент:
cbind.data.frame(a=data$a, mycol = rowSums(data[, -1], na.rm = TRUE))
который дает:
> cbind.data.frame(a=data$a, mycol = rowSums(data[, -1], na.rm = TRUE))
a mycol
1 A 1
2 B 2
3 C 3
4 D 4
5 E 5
Вы должны вызвать метод напрямую (cbind.data.frame
) как первый аргумент выше не является фреймом данных.
Что-то вроде этого?
data.frame(a=data$a, mycol=apply(data[,-1],1,sum,na.rm=TRUE))
дает:
a mycol
1 A 1
2 B 2
3 C 3
4 D 4
5 E 5
Одна возможность использования dplyr
а также tidyr
может быть:
data %>%
gather(variables, mycol, -1, na.rm = TRUE) %>%
select(-variables)
a mycol
1 A 1
2 B 2
8 C 3
14 D 4
15 E 5
Здесь он преобразует данные из широкого в длинный формат, исключая первый столбец из этой операции и удаляя NA.
Макс тоже работает. Также работает со строками-векторами.
cbind(data[1], mycol=apply(data[-1], 1, max, na.rm=T))
Если вы хотите придерживаться базы,
data <- data.frame('a' = c('A','B','C','D','E'),'x' = c(1,2,NA,NA,NA),'y' = c(NA,NA,3,NA,NA),'z' = c(NA,NA,NA,4,5))
data[is.na(data)]<-","
data$mycol<-paste0(data$x,data$y,data$z)
data$mycol <- gsub(',','',data$mycol)
Хотя это и не случай ОП, некоторым людям нравится подход, основанный на суммах, как насчет среднего и модального мышления, чтобы сделать ответ более универсальным. Этот ответ совпадает с заголовком, который многие найдут.
data <- data.frame('a' = c('A','B','C','D','E'),
'x' = c(1,2,NA,NA,9),
'y' = c(NA,6,3,NA,5),
'z' = c(NA,NA,NA,4,5))
splitdf<-split(data[,c(2:4)], seq(nrow(data[,c(2:4)])))
data$mean<-unlist(lapply(splitdf, function(x) mean(unlist(x), na.rm=T) ) )
data$mode<-unlist(lapply(splitdf, function(x) {
tab <- tabulate(match(x, na.omit(unique(unlist(x) ))));
paste(na.omit(unique(unlist(x) ))[tab == max(tab) ], collapse = ", " )}) )
data
a x y z mean mode
1 A 1 NA NA 1.000000 1
2 B 2 6 NA 4.000000 2, 6
3 C NA 3 NA 3.000000 3
4 D NA NA 4 4.000000 4
5 E 9 5 5 6.333333 5
В связанной ссылке ( подавить NA в paste ()) я представляю версию paste
с na.rm
вариант (с неудачным именем paste5
).
С этим код становится
cols <- c("x", "y", "z")
cbind.data.frame(a = data$a, mycol = paste2(data[, cols], na.rm = TRUE))
Выход из paste5
это символ, который работает, если у вас есть символьные данные, в противном случае вам нужно будет привести к нужному типу.