【问题标题】:How to create a table like contrasts in r如何在 r 中创建类似对比的表格
【发布时间】:2018-10-06 10:10:36
【问题描述】:

我需要帮助将具有某些值的数据框转换为在 R 中看起来像对比的列。 例如。

code <- data.frame(code = c('R1111', 'R1112', 'R1111', 'R1111', 'R1113', 
                            'R1112', 'R1112', 'R1112', 'R1113', 'R1115')) 

我需要将其转换为下表

    code   R1111  R1112   R1113   R1115
1  R1111     1      0       0       0
2  R1112     0      1       0       0
3  R1111     2      0       0       0 
4  R1111     3      0       0       0 
5  R1113     0      0       1       0 
6  R1112     0      2       0       0 
7  R1112     0      3       0       0 
8  R1112     0      4       0       0 
9  R1113     0      0       2       0 
10 R1115     0      0       0       1 

我有 1400 行包含我需要转换的这些类型的代码。如果您注意到,带有代码的每一列的数字都在增加。我尝试使用reshape2 执行此操作,但我不断收到错误 - 这意味着我无法弄清楚这一点。我怎样才能得到这个结果?

【问题讨论】:

  • 你试过用reshape2做什么?
  • 只是meltcast .. 尝试和学习。但没有什么具体的。我什至不确定我的代码是否正确。

标签: r reshape contrast


【解决方案1】:

一个相当简单的基本解决方案:

m  <- sapply(unique(code$code),'==',code$code)
m2 <- apply(m,2,cumsum)
m2[!m] <- 0
cbind(code,`colnames<-`(m2,unique(code$code)))

#     code R1111 R1112 R1113 R1115
# 1  R1111     1     0     0     0
# 2  R1112     0     1     0     0
# 3  R1111     2     0     0     0
# 4  R1111     3     0     0     0
# 5  R1113     0     0     1     0
# 6  R1112     0     2     0     0
# 7  R1112     0     3     0     0
# 8  R1112     0     4     0     0
# 9  R1113     0     0     2     0
# 10 R1115     0     0     0     1

【讨论】:

    【解决方案2】:

    sapply 能够做到这一点:我将code 存储为向量并进行一些后处理以生成实际的data.frame

    code <- c("R1111", "R1112", "R1111", "R1111", "R1113", "R1112", "R1112", 
    "R1112", "R1113", "R1115")
    
    val <- sapply(sort(unique(code)), function(thiscode) 
      (code==thiscode)*cumsum(code==thiscode)
    )
    

    输出是一个矩阵

          R1111 R1112 R1113 R1115
     [1,]     1     0     0     0
     [2,]     0     1     0     0
     [3,]     2     0     0     0
     [4,]     3     0     0     0
     [5,]     0     0     1     0
     [6,]     0     2     0     0
     [7,]     0     3     0     0
     [8,]     0     4     0     0
     [9,]     0     0     2     0
    [10,]     0     0     0     1
    

    并对其进行格式化,从而得到所需的输出。

    val <- data.frame(code=code, val)
    

    【讨论】:

    • 没有达到 op 的目标
    • @griffinevo 感谢您让我知道。我对outer 的这种行为感到惊讶,我应该更多地研究它。这是一个sapply 版本,经过更仔细的检查,可以按需要进行操作。
    • 太好了,感谢更新 - 我撤回了我的反对票 :)
    【解决方案3】:

    Base R 方法(它会抛出一些警告,你可以忽略它们):

    x <- code$code
    y <- rep(0, length(x))
    
    DF <- data.frame(x, y, y, y, y)
    DF[,2][DF[,1]==unique(x)[1]] <- 1:length(x)
    DF[,3][DF[,1]==unique(x)[2]] <- 1:length(x)
    DF[,4][DF[,1]==unique(x)[3]] <- 1:length(x)
    DF[,5][DF[,1]==unique(x)[4]] <- 1:length(x)
    

    如果你有很多列要处理,或者将它包装在一个循环中:

    DF <- data.frame(x, y, y, y, y)
    for(i in 1:4){
      DF[,i+1][DF[,1]==unique(x)[i]] <- 1:length(x)
    }
    

    【讨论】:

      【解决方案4】:

      您可以使用model.matrix 来生成虚拟矩阵。然后将它乘以值的数量。

      # calculate indicator using base or data.table, more succinctly
      # code$tag = with(code, as.numeric(ave(as.character(code), code, 
      #                                  FUN=function(x) cumsum(duplicated(x))+1L)))
      code$tag = data.table::rowid(code$code) 
      
      model.matrix(~ 0 + code, data=code)* code$tag
      #    codeR1111 codeR1112 codeR1113 codeR1115
      # 1          1         0         0         0
      # 2          0         1         0         0
      # 3          2         0         0         0
      # 4          3         0         0         0
      # 5          0         0         1         0
      # 6          0         2         0         0
      # 7          0         3         0         0
      # 8          0         4         0         0
      # 9          0         0         2         0
      # 10         0         0         0         1
      

      【讨论】:

        【解决方案5】:

        一种选择是将mapplyifelse 结合使用以获得所需的结果:

        cbind(code,mapply(function(x){
          ifelse(code$code==x,cumsum(code$code==x),0)
        }, unique(as.character(code$code))))
        
        #     code R1111 R1112 R1113 R1115
        # 1  R1111     1     0     0     0
        # 2  R1112     0     1     0     0
        # 3  R1111     2     0     0     0
        # 4  R1111     3     0     0     0
        # 5  R1113     0     0     1     0
        # 6  R1112     0     2     0     0
        # 7  R1112     0     3     0     0
        # 8  R1112     0     4     0     0
        # 9  R1113     0     0     2     0
        # 10 R1115     0     0     0     1
        

        【讨论】:

        • 为什么将mapply 用于单参数函数?
        • @AdamO 这只是一个想法。您可以使用do.call 等获得相同的结果。mapply 并不重要。
        猜你喜欢
        • 1970-01-01
        • 2017-09-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多