2

我不知道使用dcast()是否正确,但我想重塑以下data.frame:

df <- data.frame(x=c("p1","p1","p2"),y=c("a","b","a"),z=c(14,14,16))
df
   x y  z
1 p1 a 14
2 p1 b 14
3 p2 a 16

所以它看起来像这样:

df2 <- data.frame(x=c("p1","p2"),a=c(1,1),b=c(1,0),z=c(14,16))
   x a b  z
1 p1 1 1 14
2 p2 1 0 16

变量yindf应该被破坏,以便它的元素是新变量,每个虚拟编码。所有其他变量(在本例z中为 )对于每个人(p1、p2 等)都是相等的。特定人 p 具有不同值的唯一变量是y
我想要这个的原因是因为我需要通过变量将此数据集与其他数据集合并x。问题是,它必须是每人一行(p1,p2 等)。

4

4 回答 4

2

以下工作,但似乎很麻烦。

df2 <- df
df2$y <- as.numeric(y)
df$y2 <- as.numeric(df$y)

df2 <- dcast(df, x+z~y, value.var="y2")

df2
   x  z a  b
1 p1 14 1  2
2 p2 16 1 NA
于 2013-08-07T20:52:21.647 回答
2

这几乎是先前问题的重复,并且我在那里使用的相同基本答案再次起作用。也不需要任何外部包。

aggregate(model.matrix(~ y - 1, data=df),df[c("x","z")],max)

   x  z ya yb
1 p1 14  1  1
2 p2 16  1  0

为了解释这一点,因为它看起来有点奇怪,所以model.matrix最基本的调用会为 data.frame 的每一行的每个唯一值返回一个二进制指示变量,如下所示:

  ya yb
1  1  0
2  0  1
3  1  0

如果您aggregate通过两个 id 变量(xz)获得中间结果,那么您实际上是在对以下初始 data.frame 进行操作:

   x  z ya yb
1 p1 14  1  0
2 p1 14  0  1
3 p2 16  1  0

因此,如果您在and的每个组合中取and的max值,您基本上会这样做:yaybxz

   x  z ya      yb
1 p1 14  1*max*  0
2 p1 14  0       1*max*

--collapse--

   x  z ya      yb
1 p1 14  1       1

x...并为每个独特/组合重复此z操作以给出最终结果:

   x  z ya yb
1 p1 14  1  1
2 p2 16  1  0

将其推广到更多列会有些疯狂,但可以这样做,由这个问题提供,例如:

df <- data.frame(x=c("p1","p1","p2"),y=c("a","b","a"),z=c("14","15","16"))
intm <- model.matrix(~ y + z - 1, data=df,
                 contrasts.arg = sapply(df[2:3], contrasts, contrasts=FALSE))
aggregate(intm,df[c("x")],max)

   x ya yb z14 z15 z16
1 p1  1  1   1   1   0
2 p2  1  0   0   0   1
于 2013-08-08T00:00:33.137 回答
1

我不确定你必须做多少,但如果你需要一种自动化的方法,我写了这个可能有帮助的小函数:

首次运行 dcast:

new = dcast(df, x+z~y, value.var="y")

加载到您的 R 环境中:

 # args to be passed: 
 # df is your dataframe 
 # cols is a list of format c("colname1", "colname2", ... , "colnameN")
    binarizeCols = function(df, cols){
      for(i in cols){
        column = which(colnames(df) == i)
        truthRow = is.na(df[,column])
        for(j in 1:length(truthRow)){
          if(truthRow[j] == FALSE){
            df[j,column] = 1
          }else{
             df[j,column] = 0
           }
        }
      }
      return(df)
    }

然后运行:

new = binarizeCols(new, c("a", "b"))

你得到:

     x  z  a  b
   1 p1 14 1  1 
   2 p2 16 1  0

不如使用 _apply() 快,但没有硬编码,您可以输入任何您想要的列名(也许您想在中间跳过一个?)并且您不会创建 df 的新实例。注意:我使用“=”而不是“<-”,因为我认为它正在被逐步淘汰,但如果需要,它们可以被替换。

于 2013-08-07T23:17:48.427 回答
0
df <- data.frame(x=c("p1","p1","p2","p3"),
                 y=c("a","b","a","c"),
                 z=c(14,14,16,17))  # wanted larger test case.
new <- dcast(df, x+z~y, value.var="y")
new[3:5] <- sapply(lapply(new[3:5], '%in%', unique(df$y) ), as.numeric)
new
   x  z a b c
1 p1 14 1 1 0
2 p2 16 1 0 0
3 p3 17 0 0 1

首先检查向量中的包含情况,该向量总结了可能的值以创建逻辑值列。然后通过将这些逻辑值取为 as.numeric 来“哑化”。

于 2013-08-07T21:01:41.787 回答