1
votes

fusionner les tableaux dans R, combiner les cellules si dans les deux

Salut, pouvez-vous expliquer comment je peux fusionner deux tables pour les utiliser pour générer un diagramme à morceaux?

#read input data
dat = read.csv("/ramdisk/input.csv", header = TRUE, sep="\t")

# pick needed columns and count the occurences of each entry
df1 = table(dat[["C1"]])
df2 = table(dat[["C2"]])

# rename columns
names(df1) <- c("ID", "a", "b", "c", "d")
names(df2) <- c("ID", "e", "f", "g", "h")

# show data for testing purpose
df1  
# ID   a   b   c   d 
#241  18  17  28  29 
df2
# ID   e   f   g   h 
#230  44   8  37  14 
# looks fine so far, now the problem:

# what I want to do ist merging df and df2 
# so that df will contain the overall numbers of each entry
# df should print
# ID   a   b   c   d    e   f   g   h 
#471  18  17  28  29   44   8  37  14 
# need them to make a nice piechart in the end
#pie(df) 

Je suppose que cela peut être fait avec fusion d'une manière ou d'une autre, mais je ne l'ai pas fait trouvé le bon chemin. La solution la plus proche que j'ai trouvée était la fusion (df1, df2, all = TRUE), mais ce n'était pas exactement ce dont j'avais besoin.


4 commentaires

Que diriez-vous simplement de cbind (ID = sum (df1 [1], df2 [1]), df1 [-1], df2 [-1])


Dans le résultat souhaité, l'ID est additionné. Vous avez besoin d'au moins une colonne dans les deux tables pour fusionner.


@PierreLapointe: c'est pourquoi j'ai utilisé des noms pour faire le prénom des deux "ID". Était-ce mal?


Comme il s'agit d'une table 1-d, utilisez c au lieu de cbind


3 Réponses :


1
votes

Une approche serait de empiler , puis de rbind et de faire un aggregate

rowsum(v1, group = names(v1))

pour obtenir un vector

v1 <- c(df1, df2)
tapply(v1, names(v1), sum)

Une autre approche consiste à concaténer les tables puis à utiliser tapply pour faire un grouper par sum

with(out, setNames(values, ind))

Ou avec rowsum

out <- aggregate(values ~ ., rbind(stack(df1), stack(df2)), sum)

p >


0 commentaires

0
votes

Une autre approche serait d'utiliser rbindlist de data.table et colSums pour obtenir les totaux. rbindlist avec fill = TRUE accepte toutes les colonnes, même si elles ne sont pas présentes dans les deux tables.

df1<-read.table(text="ID   a   b   c   d 
241  18  17  28  29 ",header=TRUE)
df2<-read.table(text="ID   e   f   g   h 
230  44   8  37  14" ,header=TRUE)

library(data.table)
setDT(df1)
setDT(df2)
res <- rbindlist(list(df1,df2), use.names=TRUE, fill=TRUE)
colSums(res, na.rm=TRUE)

 ID   a   b   c   d   e   f   g   h 
471  18  17  28  29  44   8  37  14 


0 commentaires

0
votes

J'ai écrit le package safejoin qui gèrent ce type de tâches de manière intuitive (j'espère!). Il vous suffit d'avoir un identifiant commun entre vos 2 tables (nous utiliserons tibble :: row_id_to_column pour cela) et vous pourrez ensuite fusionner et gérer le conflit de colonnes avec sum .

En utilisant les données de @ pierre-lapointe:

pie(unlist(res[1,])[-(1:2)])

Pour une ligne donnée (ici la première et la seule), vous pouvez obtenir votre camembert en le convertissant en vecteur avec désélectionner et supprimer les 2 premiers éléments non pertinents:

library(tibble)
# devtools::install_github("moodymudskipper/safejoin")
library(safejoin)

res <- safe_inner_join(rowid_to_column(df1),
                       rowid_to_column(df2),
                       by = "rowid",
                       conflict = sum)

res
#   rowid  ID  a  b  c  d  e f  g  h
# 1     1 471 18 17 28 29 44 8 37 14


0 commentaires