2011-02-16 2 views
2

Supposons que nous ayons 2 questions dans un sondage, l'une concerne la probabilité qu'une personne recommande une entreprise (disons qu'il y a 2 entreprises pour plus de simplicité).R: Empiler des données de questions multiples de perforation

Alors, j'ai une data.frame avec 2 colonnes pour cette question:

df.recommend <- data.frame(rep(1:5,20),rep(1:5,20)) 
colnames(df.recommend) <- c("Company1","Company2") 

Et, supposons que nous avons une autre question qui demande aux répondants de cocher une case à côté d'un attribut qu'ils croient « crises » avec l'entreprise.

Alors, j'ai une autre data.frame avec 4 colonnes pour cette question:

df.attribute <- data.frame(rep(0:1,50),rep(1:0,50),rep(0:1,50),rep(1:0,50)) 

colnames(df.attribute) <- c(
"Attribute1.Company1", 
"Attribute2.Company1", 
"Attribute1.Company2", 
"Attribute2.Company2") 

Maintenant, ce que je voudrais être en mesure de faire est étudier la façon dont les attributs 1 et 2 sont liés à l'échelle la possibilité de recommander une question, pour toutes les entreprises (société indépendante). Juste pour avoir une idée de l'inertie entre ces personnes qui sont très susceptibles de recommander et d'attribuer 1 par exemple.

Alors, je commence par lier les deux questions ensemble:

df <- cbind(df.recommend, df.attribute) 

Mon problème est d'essayer de comprendre comment empiler ces données telles que les colonnes ressemblent à:

df.stacked <- data.frame(c(df$Company1,df$Company2), 
c(df$Attribute1.Company1,df$Attribute1.Company2), 
c(df$Attribute2.Company1,df$Attribute2.Company2)) 
colnames(df.stacked) <- c("Likelihood","Attribute1","Attribute2") 

Cet exemple est simplifié dans une large mesure. Dans mon problème actuel, j'ai 34 entreprises et 24 attributs. Pourriez-vous imaginer un moyen de les empiler efficacement, sans avoir à taper toutes les instructions c()?

Remarque: Le modèle de colonne pour probabilités est Co1, Co2, Co3, Co4 ... et le modèle pour les attributs est At1.Co1, At2.Co1, At3.Co1 ... At1.Co34, At2.Co34 ...

+0

est la structure de 'df.stacked' ce que vous pense que ça devrait être? Le 'str' de' df.stacked' renvoie "' data.frame: 2 obs de 300 variables' " – Chase

+0

Mis à jour. Merci d'avoir attrapé cette Chase. –

+0

Juste pour m'assurer que je suis sur la même page, les données finales.le cadre devrait avoir les dimensions de 34 * n lignes et 25 colonnes (1 colonne pour la variable Likelihood, et 24 pour chaque attribut? – Chase

Répondre

4

Pour ce type de problème, le paquet de refonte de Hadley est l'outil parfait. Je le combine avec quelques instructions stringr et plyr (aussi des paquets écrits par Hadley).

Voici ce que je crois être une solution complète dans environ une douzaine de lignes de code.

En premier lieu, créer des données

library(reshape2) # EDIT 1: reshape2 is faster 
library(stringr) 
library(plyr) 

# Create data frame 
# Important: note the addition of a respondent id column 

df_comp <- data.frame(
     RespID = 1:10, 
     Company1 = rep(1:5, 2), 
     Company2 = rep(1:5, 2) 
) 

df_attr <- data.frame(
     RespID = 1:10, 
     Attribute1.Company1 = rep(0:1,5), 
     Attribute2.Company1 = rep(1:0,5), 
     Attribute1.Company2 = rep(0:1,5), 
     Attribute2.Company2 = rep(1:0,5) 
) 

maintenant commencer la manipulation des données:

# Use melt to convert data from wide to tall 

melt_comp <- melt(df_comp, id.vars="RespID") 
melt_comp <- rename(melt_comp, c(variable="comp", value="likelihood")) 
melt_attr <- melt(df_attr, id.vars="RespID") 

# Use str_split to split attribute variables into attribute and company 
# "." period needs to be escaped 

# EDIT 2: reshape::colsplit is simpler than str_split 
split <- colsplit(melt_attr$variable, "\\.", names=c("attr", "comp")) 
melt_attr <- data.frame(melt_attr, split) 
melt_attr$variable <- NULL 

# Use cast to convert from tall to somewhat tall 

cast_attr <- cast(melt_attr, RespID + comp ~ attr, mean) 


# Combine data frames using join() in package plyr 

df <- join(melt_comp, cast_attr) 
head(df) 

Et la sortie:

RespID  comp likelihood Attribute1 Attribute2 
1  1 Company1   1   0   1 
2  2 Company1   2   1   0 
3  3 Company1   3   0   1 
4  4 Company1   4   1   0 
5  5 Company1   5   0   1 
6  6 Company1   1   1   0 
+0

Andrie, merci pour cela. J'ai été capable d'utiliser ce processus non seulement pour mon problème original, mais aussi, avec des ajustements mineurs, à des problèmes supplémentaires que j'avais avec la manipulation de données.Appréciez également les commentaires explicatifs! –

1

Quelque chose que j'ai rapidement concocté. Ne regardez pas le meilleur et utilise une boucle for, mais cela ne devrait pas être un problème avec seulement 24 valeurs

df.recommend <- data.frame(rep(1:5,20),rep(1:5,20)) 
colnames(df.recommend) <- c("Co1","Co2") 

df.attribute <- data.frame(rep(0:1,50),rep(1:0,50),rep(0:1,50),rep(1:0,50)) 

colnames(df.attribute) <- c(
"At1.Co1", 
"At2.Co1", 
"At1.Co2", 
"At2.Co2") 


df.stacked <- data.frame(
    likelihood <- unlist(df.recommend) 
    ) 
str <- strsplit(names(df.attribute),split="\\.") 
atts <- unique(sapply(str,function(x)x[1])) 

for (i in 1:length(atts)) 
{ 
    df.stacked[,i+1] <- unlist(df.attribute[sapply(str,function(x)x[1]==atts[i])]) 
} 

names(df.stacked) <- c("likelihood",paste("attribute",1:length(atts),sep="")) 

EDIT: Il suppose que les entreprises sont dans le même ordre pour chaque attribut