1
votes

Valeur de recherche basée sur plusieurs colonnes dans le bloc de données

J'essaie de comprendre comment rechercher une valeur en utilisant plusieurs colonnes. Je n'arrive tout simplement pas à le faire fonctionner correctement. Voici un exemple:

  g1 g2 value
1  a  1   100
2  b  2   200
3  c  3    NA
4  c  4   300

J'ai donc essayé de faire:

df1$value <- df2[match(df1$g1, df2$g.1) & match(df1$g2, df2$g.2),]$val

Mais cela ne fonctionne pas pour la dernière valeur et je devine cela ne fonctionne que pour les 2 premiers juste par erreur. J'aimerais que df1 ressemble à:

df1 <- data.frame(g1 = c("a", "b", "c", "c"), g2 = c(1, 2, 3, 4))
df2 <- data.frame(g.1 = c("a", "b", "c"), g.2 = c(1, 2, 4), val = c(100, 200, 300))


6 commentaires

Faites simplement une jointure setDT (df1) [df2, value: = val, on =. (G1, g2)]


De plus, match renvoie un index numérique, donc le & ne fonctionnera pas comme vous le souhaitez


setDT fait-il partie de la base R? (essayant de rester dans les packages de base R si possible mais intéressé par d'autres packages également)


C'est la syntaxe data.table, mais si vous voulez la base R, alors merge est mieux


Les changements de noms de colonnes peuvent être reflétés avec setDT (df1) [df2, value: = val, on =. (G1 = g.1, g2 = g.2)]


@akrun, n'hésitez pas à ajouter cela comme réponse


3 Réponses :


2
votes

Essayez une jointure gauche en utilisant merge:

transform(df1, val = df2$val[match(paste(g1, g2), paste(df2$g.1, df2$g.2))])

library(sqldf)
sqldf("select df1.*, df2.val 
       from df1 left join df2 on g1 = [g.1] and g2 = [g.2]")

library(dplyr)
df1 %>% left_join(df2, by = c(g1 = "g.1", g2 = "g.2"))

giving:

  g1 g2 val
1  a  1 100
2  b  2 200
3  c  3  NA
4  c  4 300

Voici quelques alternatives:

merge(df1, df2, by = 1:2, all.x = TRUE)


1 commentaires

a mis à jour la question pour montrer que les colonnes du groupe sont différentes. Je suppose donc que je devrais utiliser "par" avec fusion.



1
votes

Une jointure serait meilleure et avec data.table , elle devient plus efficace car nous mettons à jour ma référence

p1 <- do.call(paste, df1)
p2 <- do.call(paste, df2[1:2])
i1 <- match(p1, p2, nomatch = 0)
i2 <- match(p2, p1, nomatch = 0)
df1$value[i2] <- df2$val[i1]
df1
#  g1 g2 value
#1  a  1   100
#2  b  2   200
#3  c  3    NA
#4  c  4   300

Avec match , une approche serait de coller les colonnes d'intérêt ensemble, puis de créer un seul index pour changer les valeurs

library(data.table)
setDT(df1)[df2, value := val, on = .(g1 = g.1, g2 = g.2)]
df1
#    g1 g2 value
#1:  a  1   100
#2:  b  2   200
#3:  c  3    NA
#4:  c  4   300


0 commentaires

0
votes

J'ai compris ce que je fais de mal en me basant sur @G. Réponse de Grothendieck. Tout ce que j'avais à faire était:

df1$value <- df2[match(paste0(df1$g1,df1$g2), paste0(df2$g.1,df2$g.2)),]$val


0 commentaires