2012-09-12 7 views
0

J'ai un grand cadre de données de similarités entre les mots-clés que je voudrais changer en un format qui inclut toutes les similitudes par paires. Mon trame de données actuelle ressemble à:Convertir la trame de données R

> df 
    kwd1 kwd2 sim 
1 a b 1 
2 b a 1 
3 c a 2 
4 a c 2 

et je voudrais le convertir en un data.frame de la forme:

> df 
    kwd1 kwd2 sim 
    a b 1 
    a c 2 
    b c 0 

Merci pour toute aide!

Mon code à ce jour est:

df <- data.frame(c('a', 'b', 'c', 'a'), c('b', 'a', 'a', 'c'), c(.1,.1,.2,.2)) 
colnames(df) = c('kwd1', 'kwd2', 'sim') 
> dput(df) 
structure(list(kwd1 = structure(c(1L, 2L, 3L, 1L), .Label = c("a", 
"b", "c"), class = "factor"), kwd2 = structure(c(2L, 1L, 1L, 
3L), .Label = c("a", "b", "c"), class = "factor"), sim = c(1, 
1, 2, 2)), .Names = c("kwd1", "kwd2", "sim"), row.names = c(NA, 
-4L), class = "data.frame") 

Répondre

2
library(plyr) 
res <- merge(expand.grid(kwd1 = unique(c(df$kwd1, df$kwd2)), 
kwd2 = unique(c(df$kwd1, 
    df$kwd2))), df, all.x = T) 

res <- ddply(res, .(kwd1, kwd2), function(x) { 
    if (which(letters == x$kwd1) != which(letters == x$kwd2)) { 
     if (which(letters == x$kwd1) > which(letters == x$kwd2)) { 
      return(data.frame(kwd1 = x$kwd2, kwd2 = x$kwd1, sim = x$sim)) 
     } else { 
      return(x) 
     } 
    } 
}) 
res1 <- res[!duplicated(res), ] 

> res1 
    kwd1 kwd2 sim 
1 a b 0.1 
2 a c 0.2 
4 b c NA 

Vous pouvez simplement tourner ceci dans une fonction pour le rendre plus facile à appeler.

convert_df <- function(df) { 
    res <- merge(expand.grid(kwd1 = unique(c(df$kwd1, df$kwd2)), 
kwd2 = unique(c(df$kwd1, 
    df$kwd2))), df, all.x = T) 
res <- ddply(res, .(kwd1, kwd2), function(x) { 
    if (which(letters == x$kwd1) != which(letters == x$kwd2)) { 
     if (which(letters == x$kwd1) > which(letters == x$kwd2)) { 
      return(data.frame(kwd1 = x$kwd2, kwd2 = x$kwd1, sim = x$sim)) 
     } else { 
      return(x) 
     } 
    } 
}) 
return(res[!duplicated(res), ]) 
} 
# Then simply run this to convert your actual data.frame 
convert_df(df) 
+0

Votre résultat ne correspond pas à celui souhaité dans la question. –

+0

J'ai noté sur ma première ligne que cela ne fonctionne que si l'ordre n'a pas d'importance. – Maiasaura

+0

Je l'ai vu, mais il semble clair d'après la question qu'une seule des lignes 'a b 0.1' et 'b a 0.1' est censée rester. Il n'a pas dit lequel des deux avait la priorité, et j'ai supposé que c'était ce que votre mise en garde s'adressait. –

0

Il pourrait y avoir une façon plus élégante là-bas, mais c'est une façon de le faire:

# make a data.frame with all possible combinations of kwd1 and kwd2. 
# the ones that aren't in df are NA for sim. 
k <- merge(expand.grid(kwd1=df$kwd1, kwd2=df$kwd2), df, all=TRUE) 
# order the result to put the NA rows at the end, so that rows that are in df 
# have priority in the following step. 
k <- k[order(k$sim), ] 
# remove all rows where the kwd1-kwd2 combo appears earlier in the data.frame 
k <- k[! duplicated(apply(k[1:2], MARGIN=1, sort), MARGIN=2), ] 
# assuming you don't want the rows where kwd1 and kwd2 are the same, remove them. 
k <- subset(k, kwd1 != kwd2) 
# set the NA values to 0 
k[is.na(k)] <- 0 

    kwd1 kwd2 sim 
5  a b 0.1 
7  a c 0.2 
12 b c 0.0 
+0

J'ai essayé ceci sur un plus grand ensemble de données et cela n'a pas fonctionné. – rfoley

+0

Qu'est-ce que vous avez obtenu que vous ne vouliez pas? –

+0

Je viens de réaliser qu'il y avait une faute de frappe sur la dernière ligne. il lit 'k <- k [is.na (k)] <- 0'. Avez-vous obtenu 'k' égal à zéro? Si oui, c'est pourquoi. –

Questions connexes