Puis-je définir une valeur de "remplissage" pour NA dans la jointure dplyr? Par exemple, dans la jointure, définissez que toutes les valeurs NA doivent être 1?
require(dplyr)
lookup <- data.frame(cbind(c("USD","MYR"),c(0.9,1.1)))
names(lookup) <- c("rate","value")
fx <- data.frame(c("USD","MYR","USD","MYR","XXX","YYY"))
names(fx)[1] <- "rate"
left_join(x=fx,y=lookup,by=c("rate"))
Le code ci-dessus créera NA pour les valeurs "XXX" et "YYY". Dans mon cas, je rejoins un grand nombre de colonnes et il y aura beaucoup de non-correspondances. Toutes les non-correspondances doivent avoir la même valeur. Je sais que je peux le faire en plusieurs étapes, mais la question est: tout peut-il être fait en une seule? Merci!
Tout d'abord, je voudrais recommander de ne pas utiliser la combinaison data.frame(cbind(...))
. Voici pourquoi: cbind
crée un matrix
par défaut si vous ne lui passez que des vecteurs atomiques. Et les matrices dans R ne peuvent avoir qu'un seul type de données (pensez aux matrices comme un vecteur avec un attribut de dimension, c'est-à-dire le nombre de lignes et de colonnes). Par conséquent, votre code
cbind(c("USD","MYR"),c(0.9,1.1))
crée une matrice de caractères:
str(cbind(c("USD","MYR"),c(0.9,1.1)))
# chr [1:2, 1:2] "USD" "MYR" "0.9" "1.1"
bien que vous vous attendiez probablement à une trame de données finale avec une colonne de caractère ou de facteur (taux) et une colonne numérique (valeur). Mais ce que vous obtenez est:
str(data.frame(cbind(c("USD","MYR"),c(0.9,1.1))))
#'data.frame': 2 obs. of 2 variables:
# $ X1: Factor w/ 2 levels "MYR","USD": 2 1
# $ X2: Factor w/ 2 levels "0.9","1.1": 1 2
car les chaînes (caractères) sont converties en facteurs lors de l'utilisation de data.frame
par défaut (vous pouvez contourner cela en spécifiant stringsAsFactors = FALSE
dans l'appel data.frame()
).
Je suggère l'approche alternative suivante pour créer les exemples de données (notez également que vous pouvez facilement spécifier les noms de colonne dans le même appel):
lookup <- data.frame(rate = c("USD","MYR"),
value = c(0.9,1.1))
fx <- data.frame(rate = c("USD","MYR","USD","MYR","XXX","YYY"))
Maintenant, pour votre question réelle, si je comprends bien, vous voulez remplacer tous les NA
s par un 1
Dans les données jointes. Si c'est correct, voici une fonction personnalisée utilisant left_join
Et mutate_each
Pour ce faire:
library(dplyr)
left_join_NA <- function(x, y, ...) {
left_join(x = x, y = y, by = ...) %>%
mutate_each(funs(replace(., which(is.na(.)), 1)))
}
Vous pouvez maintenant l'appliquer à vos données comme ceci:
> left_join_NA(x = fx, y = lookup, by = "rate")
# rate value
#1 USD 0.9
#2 MYR 1.1
#3 USD 0.9
#4 MYR 1.1
#5 XXX 1.0
#6 YYY 1.0
#Warning message:
#joining factors with different levels, coercing to character vector
Notez que vous vous retrouvez avec une colonne de caractères (taux) et une colonne numérique (valeur) et toutes les NA sont remplacées par 1.
str(left_join_NA(x = fx, y = lookup, by = "rate"))
#'data.frame': 6 obs. of 2 variables:
# $ rate : chr "USD" "MYR" "USD" "MYR" ...
# $ value: num 0.9 1.1 0.9 1.1 1 1
Si vous utilisez dplyr de toute façon, vous pourriez tout aussi bien profiter de dplyr::coalesce
, et utilisez la syntaxe dplyr pour y passer un 1 ou 0. Je pense que ça a l'air sympa ...
... %>%
mutate_if(is.numeric,coalesce,0)
Où le 0
est l'argument passé à dplyr::coalesce
pour remplacer les NA.
Dans l'exemple de la question, il existe des cadres de données avec des facteurs. Je suis convaincu que l'on ne disposerait pas de taux de change comme facteurs ou d'un autre vecteur dans lequel vous remplaceriez NA par zéro, alors j'avance et j'ajoute cette étape ci-dessous juste pour rendre la réponse exécutable après l'exemple fourni.
# replace NAs with zeros for all numeric columns
#
# ... code from question above
left_join(x=fx,y=lookup,by=c("rate")) %>%
# ignore if factors in value column are because it's a toy example
mutate(value = as.numeric(as.character(value))) %>%
# the good stuff here
mutate_if(is.numeric,coalesce,0)
Je suis tombé sur le même problème avec dplyr et j'ai écrit une petite fonction qui a résolu mon problème. (la solution nécessite tidyr et dplyr)
left_join0 <- function(x, y, fill = 0L){
z <- left_join(x, y)
tmp <- setdiff(names(z), names(x))
z <- replace_na(z, setNames(as.list(rep(fill, length(tmp))), tmp))
z
}
Réponse initiale à: R Jointure externe gauche avec remplissage 0 au lieu de NA tout en conservant des NA valides dans le tableau de gauche