【问题标题】:reshape dataframe based on a string split in one column in R根据 R 中一列中拆分的字符串重塑数据框
【发布时间】:2012-09-22 08:06:05
【问题描述】:

我有以下数据结构

ID  Type  Values
1   A     5; 7; 8
2   A     6
3   B     2; 3

我想使用 R 将其重塑为以下内容:

ID  Type  Values
1   A     5
1   A     7
1   A     8
2   A     6
3   B     2
3   B     3

我一直在尝试使用 plyr 解决此问题,但没有任何成功。最好的方法是什么?

【问题讨论】:

    标签: r dataframe reshape


    【解决方案1】:

    这应该可行,但也许有更好的方法:

    #recreate data set
    dat <- data.frame(ID=1:3, Type=c("A", "A", "B"), Values=c("5; 7; 8", "6", "2; 3"))
    #split the Value column by ;
    a <- strsplit(as.character(dat$Values), ";", fixed=TRUE)
    #remove extra white
    a <- lapply(a, function(x) gsub("^\\s+|\\s+$", "", x))
    #get the length of each cell in Value so we can use this to index the rows
    lens <- sapply(a, length)
    #index rows and rename row names to numeric indexes
    dat2 <- dat[rep(1:nrow(dat), lens), 1:2]
    rownames(dat2) <- NULL
    #add the stretched new column back
    dat2$Value <- as.numeric(unlist(a))
    

    【讨论】:

      【解决方案2】:

      不是一个漂亮的答案,但它可能有用

      DF <- data.frame(ID=1:3,
                       Type=c('A','A','B'), 
                       Values=c(' 5; 7; 8', '6', ' 2;3')) # this is your df
      
          # split vectors and coercing values to be numeric
          List <- lapply(strsplit(Values, ';'), as.numeric)
      
      # The desired output
          data.frame(ID=rep(ID, sapply(List, length)), 
                     Type=rep(Type, sapply(List, length)),
                     Values =   unlist(List))
       ID Type Values
      1  1    A      5
      2  1    A      7
      3  1    A      8
      4  2    A      6
      5  3    B      2
      6  3    B      3
      

      【讨论】:

      • 有趣的是,我最终得到了几乎完全正确的解决方案!
      【解决方案3】:

      既然您要求plyr 解决方案,那么您就去吧:

      ddply(df, .(Type), function(foo) {
          values <- unlist(strsplit(c(foo$Values), ";"))
          data.frame(Type = rep(unique(foo$Type), length(values)), Values = values)
          })
      

      【讨论】:

      • 我认为这对 plyr 来说很难。不是这样,谢谢你证明我的想法是错误的。 +1
      【解决方案4】:

      我的镜头:

      a <- data.frame(id = 1:3, 
                      type = c("A", "A", "B"), 
                      values = c("5; 7; 8", "6", "2; 3"))
      
      g <- strsplit(as.character(a$values), ";")
      data.frame(id = rep(a$id, lapply(g, length)), 
                  type = rep(a$type, lapply(g, length)),
                  values = unlist(g))
      

      【讨论】:

        【解决方案5】:

        到目前为止的答案都很棒。这是另一个。

        # The data
        DF <- data.frame(ID=1:3,
                         Type=c('A','A','B'), 
                         Values=c(' 5; 7; 8', '6', ' 2;3'))
        

        此解决方案使用“reshape2”包中的colsplit() 函数。一个缺点是它希望您知道所需的结果列数。

        require(reshape2)
        DF2 <- data.frame(DF[-3], colsplit(DF$Values, ";", c("V.1", "V.2", "V.3")))
        na.omit(melt(DF2, id.vars=c("ID", "Type")))
        #   ID Type variable value
        # 1  1    A      V.1     5
        # 2  2    A      V.1     6
        # 3  3    B      V.1     2
        # 4  1    A      V.2     7
        # 6  3    B      V.2     3
        # 7  1    A      V.3     8
        

        您可以在此处根据需要对列进行排序和删除,以获得最终所需的输出。

        【讨论】:

          【解决方案6】:

          data.table 编码优雅的方法

          library(data.table)
          DT <- data.table(dat)
          DT[, list(Value = unlist(strsplit(as.character(Values), '; '))), by = list(ID, Type)]
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-09-11
            • 1970-01-01
            • 1970-01-01
            • 2021-08-23
            • 1970-01-01
            相关资源
            最近更新 更多