J'ai quelques colonnes dans R et pour chaque ligne, il n'y aura jamais qu'une valeur dans l'une d'entre elles, le reste sera constitué de NA. Je veux les combiner dans une colonne avec la valeur non-NA. Est-ce que quelqu'un connaît un moyen facile de le faire? Par exemple, je pourrais avoir comme suit:
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))
Donc j'aurais
'a' 'x' 'y' 'z'
A 1 NA NA
B 2 NA NA
C NA 3 NA
D NA NA 4
E NA NA 5
Et je voudrais obtenir
'a' 'mycol'
A 1
B 2
C 3
D 4
E 5
Les noms des colonnes contenant NA changent en fonction du code précédemment dans la requête. Par conséquent, je ne pourrai pas appeler les noms de colonne explicitement, mais j'ai les noms des colonnes contenant les NA stockés sous forme de vecteur, par exemple. Dans cet exemple, cols <- c('x','y','z')
, alors pourrait appeler les colonnes en utilisant data[, cols]
.
Toute aide serait appréciée.
Merci
Vous pouvez utiliser unlist
pour transformer les colonnes en un seul vecteur. na.omit
peut ensuite être utilisé pour supprimer les 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
Une solution basée sur dplyr::coalesce
pourrait être la suivante:
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
Les données
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))
Voici une solution plus générale (mais encore plus simple) qui s'étend à tous les types de colonnes (facteurs, caractères, etc.) avec des NA non ordonnés. La stratégie consiste simplement à fusionner les valeurs non-NA d'autres colonnes dans votre colonne fusionnée en utilisant is.na
pour l'indexation:
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
Notez que cela écrasera les valeurs existantes dans m
s'il existe plusieurs valeurs non NA dans la même ligne. Si vous avez beaucoup de colonnes, vous pouvez automatiser cela en bouclant sur colnames(data)
.
J'utiliserais rowSums()
avec l'argument na.rm = TRUE
:
cbind.data.frame(a=data$a, mycol = rowSums(data[, -1], na.rm = TRUE))
qui donne:
> 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
Vous devez appeler la méthode directement (cbind.data.frame
) car le premier argument ci-dessus n'est pas un cadre de données.
Quelque chose comme ça ?
data.frame(a=data$a, mycol=apply(data[,-1],1,sum,na.rm=TRUE))
donne:
a mycol
1 A 1
2 B 2
3 C 3
4 D 4
5 E 5
max fonctionne aussi. Fonctionne également sur les vecteurs de chaînes.
cbind(data[1], mycol=apply(data[-1], 1, max, na.rm=T))
Dans un lien connexe ( supprimer les NA en pâte () ), je présente une version de paste
avec une option na.rm
(avec le nom malheureux de paste5
).
Avec cela le code devient
cols <- c("x", "y", "z")
cbind.data.frame(a = data$a, mycol = paste2(data[, cols], na.rm = TRUE))
La sortie de paste5
est un caractère, ce qui fonctionne si vous avez des données de caractère, sinon vous devrez forcer le type que vous voulez.
Bien que ce ne soit pas le cas du PO, il semble que certaines personnes aiment l’approche basée sur les sommes, qu’en est-il de penser en mode et en mode, pour rendre la réponse plus universelle. Cette réponse correspond au titre, qui est ce que beaucoup de gens vont trouver.
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