【问题标题】:Rearrange and Sort重新排列和排序
【发布时间】:2018-03-02 14:39:43
【问题描述】:

我有以下数据

ID v1 v2 v3 v4 v5 
1  1  3  6  4
2  4  2
3  3  1   8    5
4  2  5   3    1

我可以重新排列数据,以便它会根据每个变量(v1 到 v5)中的值自动创建新列并分配二进制值(1 或 0)吗?

例如在第一行,我有 1、3、4 和 6 的值。R 可以自动创建 6 个虚拟变量以将值分配给相应的列,如下所示:

 ID dummy1 dummy2 dummy3 dummy4 dummy5 dummy6
 1    1     0      1      1      0       1

拥有这样的东西:

ID c1 c2 c3 c4 c5 c6 c7 c8
1  1  0  1  1  0  1  0  0
2  0  1  0  1  0  0  0  0
3  1  0  1  0  1  0  0  1
4  1  1  1  0  1  0  0  0 

谢谢。

【问题讨论】:

  • melt 然后dcast 使用“data.table”的数据(或gatherspread 使用“tidyverse”)。

标签: r binary reshape


【解决方案1】:

我们可以使用base R 来执行此操作。遍历数据集除第一列以外的行,获取行中max值的序列,检查行中有多少个,将其转换为integeras.integer,追加NAs最后使list 输出和cbind 与第一列的长度相同

lst <- apply(df[-1], 1, function(x) as.integer(seq_len(max(x, na.rm = TRUE)) %in% x))
res <- cbind(df[1], do.call(rbind, lapply(lst, `length<-`, max(lengths(lst)))))
res[is.na(res)] <- 0
colnames(res)[-1] <- paste0('c', 1:8)
res
#  ID c1 c2 c3 c4 c5 c6 c7 c8
#1  1  1  0  1  1  0  1  0  0
#2  2  0  1  0  1  0  0  0  0
#3  3  1  0  1  0  1  0  0  1
#4  4  1  1  1  0  1  0  0  0

【讨论】:

    【解决方案2】:

    在基础 R 中,您可以使用:

    table(transform(cbind(mydf[1], stack(mydf[-1]))[1:2], values = factor(values, 1:8)))
    ##    values
    ## ID  1 2 3 4 5 6 7 8
    ##   1 1 0 1 1 0 1 0 0
    ##   2 0 1 0 1 0 0 0 0
    ##   3 1 0 1 0 1 0 0 1
    ##   4 1 1 1 0 1 0 0 0
    

    请注意,如果您希望输出中包含“7”,则需要将堆叠值转换为 factor。这也适用于“data.table”和“tidyverse”方法。


    或者,您可以使用“data.table”尝试以下操作:

    library(data.table)
    melt(as.data.table(mydf), "ID", na.rm = TRUE)[
      , dcast(.SD, ID ~ factor(value, 1:8), fun = length, drop = FALSE)]
    

    或下面的“tidyverse”:

    library(tidyverse)
    mydf %>% 
      gather(var, val, -ID, na.rm = TRUE) %>% 
      select(-var) %>% 
      mutate(var = 1, val = factor(val, 1:8)) %>% 
      spread(val, var, fill = 0, drop = FALSE)
    

    样本数据:

    mydf <- structure(list(ID = 1:4, v1 = c(1L, 4L, 3L, 2L), v2 = c(3L, 2L, 
        1L, 5L), v3 = c(6L, NA, 8L, 3L), v4 = c(4L, NA, 5L, 1L), v5 = c(NA, 
        NA, NA, NA)), .Names = c("ID", "v1", "v2", "v3", "v4", "v5"), row.names = c(NA, 
        4L), class = "data.frame")
    

    如果自动化很重要,您还可以在“data.table”方法中使用factor(value, sequence(max(value)) 或在“tidyverse”方法中使用val = factor(val, sequence(max(val)))) 等语法。

    【讨论】:

      【解决方案3】:

      另一个与 akrun 相似的基本 R 答案是

      # create matrix of values
      myMat <- as.matrix(dat[-1])
      # create result matrix of desired shape, filled with 0s
      res <- matrix(0L, nrow(dat), ncol=max(myMat, na.rm=TRUE))
      # use matrix indexing to fill in 1s
      res[cbind(dat$ID, as.vector(myMat))] <- 1L
      # convert to data.frame, add ID column, and provide variable names
      setNames(data.frame(cbind(dat$ID, res)), c("ID", paste0("c", 1:8)))
      

      返回

        ID c1 c2 c3 c4 c5 c6 c7 c8
      1  1  1  0  1  1  0  1  0  0
      2  2  0  1  0  1  0  0  0  0
      3  3  1  0  1  0  1  0  0  1
      4  4  1  1  1  0  1  0  0  0
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-06-19
        • 2019-09-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-11
        • 2023-03-16
        相关资源
        最近更新 更多