1
votes

remplacer la valeur par une autre valeur en cas de correspondance

J'essaie d'utiliser une fonction de base simple pour mapper des valeurs si les deux valeurs correspondent à deux blocs de données, alors l'ancienne valeur doit rester

     a1  b1
1  sale bb2
2 sale2 cc2
3 sale3  d2

Résultat souhaité:

XXX

r

5 commentaires

voulez-vous dire faire correspondre les valeurs par position?


Je veux dire des valeurs correspondantes si elles correspondent à l'ancienne valeur correspondante sinon l'ancienne valeur de b1 de df2 pour rester


désolé, pas encore clair - comment savoir à quelle ancienne valeur appartiennent les nouvelles? Est-ce par sa position (ligne) dans le bloc de données?


oui par sa position @Tjebo


Vérifiez la réponse mise à jour - tout le mérite revient à @WaltS


3 Réponses :


1
votes

En supposant que vous entendiez faire correspondre les valeurs par position, voici une solution de base R. Cela peut être plus facile avec des paquets tels que data.table ou dplyr, mais en général bien sûr, c'est bien d'avoir une idée de l'utilisation de la base R.

Il y a certainement de meilleures façons d'obtenir le résultat ci-dessous. Je n'utilise généralement pas la base R pour ce type de jointures

# date frames from above without factors!! 

df2$new <- ifelse(df2$b1 == df1$a1, df1$b1, df2$b1)

df2
#>    sale b1 new
#> 1  sale b2 bb2
#> 2 sale2 c2 cc2
#> 3 sale3 d2  d2

Remarque J'ai changé le nom dans les blocs de données et changé les facteurs en caractères, ce qui rend la fusion possible.

La clé est de créer une variable qui permet la fusion / jointure (comment vous voulez l'appeler). J'utilise vente - cela permet de faire correspondre par position.

Merci @WaltS d'avoir indiqué une option beaucoup plus simple. Parce que la correspondance est par position, on peut faire une affectation directe de colonne:

df1 <- data.frame(a1 = c("b2","c2","abc2"), b1 = c("bb2","cc2","d2"), stringsAsFactors = FALSE)
df2 <- data.frame(sale = c("sale","sale2","sale3"), b1 = c("b2","c2","d2"), stringsAsFactors = FALSE)

df1$sale <- df2$sale

joined <- merge(df2,df1,by = 'sale')
joined$new <- ifelse(joined$b1.x == joined$b1.y, joined$b1.x, joined$b1.y)
joined[,c(1,5)]
#>    sale new
#> 1  sale bb2
#> 2 sale2 cc2
#> 3 sale3  d2

Créé le 23/02/2020 par le paquet reprex (v0.3.0)


4 commentaires

Après avoir supprimé les facteurs, vous pouvez simplement faire df2 $ b1 <- ifelse (df2 $ b1 == df1 $ a1, df1 $ b1, df2 $ b1)


@WaltS très vrai. c’est la solution de loin la plus directe. .


@WaltS voulez-vous en faire une réponse ou dois-je modifier la mienne?


Vous avez répondu en premier. J'ai juste simplifié un peu les choses.



1
votes

Je ne sais pas si cela fonctionne pour vous, mais beaucoup plus facile si vous utilisez le , comme mentionné par tjebo :

df2 <- data.frame(a1 = c("sale","sale2","sale3"),b1 = c("b2","c2","d2"),
                  stringsAsFactors = F)

Sortie

new_df
     a1   b1
1  sale   b2
2 sale2   c2
3 sale3 abc2

case_when est la manière dplyr de créer if-else construction.

Remarque

Vous devez avoir les colonnes comme n'importe quoi, sauf facteurs , pour que cela fonctionne. Ajoutez simplement stringsAsFactors = F , tout en formant le dataframe, comme ci-dessous.

new_df <- df2 %>% mutate(b1 = case_when(b1 == df1$a1 ~ b1, b1 != df1$a1 ~ df1$a1))


0 commentaires

1
votes

Voici une solution de base R, utilisant merge + ifelse , c'est-à-dire

> dfout
   a1.y  b1
1  sale bb2
2 sale2 cc2
3 sale3  d2

telle que

dfout <- rev(within(merge(df1,df2,by.x = "a1",by.y = "b1",all.y = TRUE),
                    b1 <- ifelse(is.na(b1),as.character(a1),as.character(b1)))[-1])


0 commentaires