R:堆叠多个打孔问题数据

时间:2011-02-16 02:03:10

标签: r reshape

假设我们在调查中有两个问题,一个是关于个人推荐公司的可能性(假设有两家公司为了简单起见)。

所以,我有一个带有2列的data.frame:

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

并且,假设我们还有另一个问题,要求受访者在他们认为与公司“适合”的属性旁边勾选一个方框。

所以,我有另外一个包含4列的data.frame:

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") 

现在,我希望能够做的是审查属性1和2如何与所有公司(公司独立)推荐问题的可能性的规模相关。只是想知道那些极有可能推荐的人和例如1的属性之间的惯性。

所以,我首先将两个问题绑定在一起:

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

我的问题是试图找出如何堆叠这些数据,使列看起来像:

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")

此示例在很大程度上得到了简化。在我的实际问题中,我有34家公司和24个属性。

你能想出一种有效堆叠它们的方法,而不必输入所有的c()语句吗?

注意:可能性的列模式是Co1,Co2,Co3,Co4 ......属性的模式是At1.Co1,At2.Co1,At3.Co1 ... At1.Co34,At2.Co34。 ..

2 个答案:

答案 0 :(得分:4)

对于这类问题,Hadley的重塑包是完美的工具。我将它与一些stringr和plyr语句(也是Hadley编写的包)结合起来。

以下是我认为是十几行代码的完整解决方案。

首先,创建一些数据

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)
)

现在开始数据操作:

# 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)

输出:

  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

答案 1 :(得分:1)

我快点做的东西。看起来不是最好并使用for循环,但这不应该是只有24个值的问题

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=""))

编辑:它假定公司对每个属性的顺序相同