2013-03-14 44 views
1

我需要以不同的方式查看数据框中的数据。这里的问题..R数据转换

我有一个数据帧如下

Person Item BuyOrSell 
1  a B 
1  b S 
1  a S 
2  d B 
3  a S 
3  e S 

一个我的要求就是看数据如下。显示该人对交易类型(B或S)

Person aB aS bB bS dB dS eB eS 
1   1 1 0 1 0 0 0  0 
2   0 0 0 0 1 0 0  0 
3   1 0 0 0 0 0 0  1 

所以我创建了一个新的列和追加两个项目和BuyOrSell值破个别项目进行的所有交易的总和。

df$newcol<-paste(Item,"-",BuyOrSell,sep="") 
table(Person,newcol) 

并且能够达到上述结果。

最后转换的要求这是一个难啃的骨头是如下....

aB aS bB bS dB dS eB eS 
aB 1 1 0 1 0 0  0 0 
aS 1 2 0 1 0 0  0 1 
bB 0 0 0 0 0 0  0 0 
bS 1 1 0 0 0 0  0 0 
dB 0 0 0 0 1 0  0 0 
dS 0 0 0 0 0 0  0 0 
eB 0 0 0 0 0 0  0 0 
eS 0 1 0 0 0 0  0 1 

,其中上表必须与人谁做特定的交易也让数填写另一项目上的交易。

我试过table(newcol,newcol),但它只对aB-aB,aS-aS,bB-bB,......产生计数,而对于所有其他组合则产生0。

关于什么包或命令会让我破解这个螺母的想法?

+3

我觉得你应该先接受回答你刚才的问题:http://stackoverflow.com/questions/15417698/data-transformations-in-r – Arun 2013-03-14 20:55:54

+0

只是。谢谢Arun! – user2171177 2013-03-14 21:01:51

+0

你能解释一下你的标准吗?我有一个很难理解“其中上表必须是...另一个项目” – Arun 2013-03-14 22:16:47

回答

3

不只是最终的结果:

# Following Ricardo's solution for casting, but using `acast` instead 
A <- acast(Person~Item+BuyOrSell,data=df,fun.aggregate=length,drop=FALSE) 

# A' * A 
> t(A) %*% A 
#  a_B a_S b_B b_S d_B d_S e_B e_S 
# a_B 1 1 0 1 0 0 0 0 
# a_S 1 2 0 1 0 0 0 1 
# b_B 0 0 0 0 0 0 0 0 
# b_S 1 1 0 1 0 0 0 0 
# d_B 0 0 0 0 1 0 0 0 
# d_S 0 0 0 0 0 0 0 0 
# e_B 0 0 0 0 0 0 0 0 
# e_S 0 1 0 0 0 0 0 1 
+0

看起来很对我。非常优雅! – 2013-03-14 23:59:37

+0

这是一个很好的答案。 wonderful..thanks。 – user2171177 2013-03-15 01:31:49

1

我认为有一个更好的方法,但这里有一个方法使用包reshape2

require(reshape2) 
#reshapes data so each item and buy/sell event interaction occurs once 
df2 <- dcast(Person~Item+BuyOrSell,data=df,fun.aggregate=length,drop=FALSE) 
df2 
    # Person a_B a_S b_B b_S d_B d_S e_B e_S 
# 1  1 1 1 0 1 0 0 0 0 
# 2  2 0 0 0 0 1 0 0 0 
# 3  3 0 1 0 0 0 0 0 1 

#reshapes data so every row is an interaction by person 
df3 <- melt(df2,id.vars="Person") 
head(df3) 
    # Person variable value 
# 1  1  a_B  1 
# 2  2  a_B  0 
# 3  3  a_B  0 
# 4  1  a_S  1 
# 5  2  a_S  0 
# 6  3  a_S  1 

#removes empty rows where no action occurred 
#removes value column 
df4 <- with(df3, 
    data.frame(Person=rep.int(Person,value),variable=rep.int(variable,value)) 
#performs a self-merge: now each row is 
#every combination of two actions that one person has done 
df5 <- merge(df4,df4,by="Person") 
head(df5) 
    # Person variable.x variable.y 
# 1  1  a_B  a_B 
# 2  1  a_B  a_S 
# 3  1  a_B  b_S 
# 4  1  a_S  a_B 
# 5  1  a_S  a_S 
# 6  1  a_S  b_S 

#tabulates variable interactions 
with(df5,table(variable.x,variable.y)) 
+0

你能解释一下你的解决方案吗?尤其是DF4 – user2171177 2013-03-14 21:30:40

+0

我改变了'df4'原来是因为我以为你会算的人1两次,如果他们购买了项目A的两倍,但在重新阅读的问题,我觉得你只是想的人数。我现在改回来了。 – 2013-03-14 22:32:58

+0

您的初始解决方案非常完美。我会数一次人1。我已经在下面发布了我的答案..我根据你的解决方案对我所做的不同做了很多。请在下面对我的帖子发表评论。 – user2171177 2013-03-14 22:38:48

0

Blue Magister,您的解决方案完美工作,我分析了您执行的每一步。

DF4的产量如下:

Person variable 
1  1  a_B 
2  1  a_S 
3  3  a_S 
4  1  b_S 
5  2  d_B 
6  3  e_S 

with(df5,table(variable.x,variable.y))产量为

variable.y 
variable.x a_B a_S b_B b_S d_B d_S e_B e_S 
     a_B 1 1 0 1 0 0 0 0 
     a_S 1 2 0 1 0 0 0 1 
     b_B 0 0 0 0 0 0 0 0 
     b_S 1 1 0 1 0 0 0 0 
     d_B 0 0 0 0 1 0 0 0 
     d_S 0 0 0 0 0 0 0 0 
     e_B 0 0 0 0 0 0 0 0 
     e_S 0 1 0 0 0 0 0 1 

这正是我想要的。

当我看着D4输出它几乎类似于我NEWCOL溶液(使用膏)相比,你DF4时

> df 
    Person newcol 
1  1 a-B 
2  1 b-S 
3  1 a-S 
4  2 d-B 
5  3 a-S 
6  3 e-S 

这里唯一的不同是行的排序。

所以,我结束了在运行此命令

dfx <- merge(df,df,by="Person") 
with(dfx,table(newcol.x,newcol.y)) 

,并生成以下...

newcol.y 
newcol.x a-B a-S b-S d-B e-S 
    a-B 1 1 1 0 0 
    a-S 1 2 1 0 1 
    b-S 1 1 1 0 0 
    d-B 0 0 0 1 0 
    e-S 0 1 0 0 1 

以上输出忽略几行和列。我和你有什么不同?

+0

您应该将此文本移至单独的问题,而不是通过“答案”询问。再回到以前的问题,让人们明白你在问什么。 – 2013-03-14 22:49:07

+1

本质上,差异源于'levels(df4 $ variable)'和你的'levels(df $ newcol)'。 – 2013-03-14 22:50:47

+0

辉煌!谢谢。 – user2171177 2013-03-15 01:29:37