【问题标题】:Creating new columns by splitting a variable into many variables (in R)通过将变量拆分为多个变量来创建新列(在 R 中)
【发布时间】:2015-08-17 17:19:22
【问题描述】:

我想通过在数据框中拆分向量来创建新列。

我有这样一个数据框:

YEAR Variable1 Variable2 
2009 000000    00000001
2010 000000    00000001
2011 000000    00000001
2009 000000    00000002
2010 000000    00000002
2009 000000    00000003
...
2009 100000    10000001
2010 100000    10000001
...
2009 100000    10000011
....

如您所见,变量 2 与变量 1 相关(变量 2=变量 1+最后两位数字:例如 01、02、03... 表示子类别)。我想将变量 2 拆分为子类别这么多的变量。结果应该是:

YEAR Variable1 Variable2 Variable3 Variable4 ... 
2009 000000    00000001  0         0        
2010 000000    00000001  0         0
2011 000000    00000001  0         0
2009 000000    0         00000002  0
2010 000000    0         00000002  0
2009 000000    0         0         00000003
...
2009 100000    10000001  0         0     
2010 100000    10000001  0         0     
...
2009 100000    0         0         0       ...      10000011 

您将如何进行?我想我应该尝试在循环中重新编码 Variable2.. 我尝试通过操作字符串,但我没有解决问题..

【问题讨论】:

  • 所以取决于你想要创建列并给出值的最后两个变量,所以总共会有大约 101 列是你想要的
  • 例如,变量 1 中的第一个元素 (000000) 对应于变量 2 中的 3 个元素 (00000001, 00000002, 00000003),它们应该在三个不同的列中重写。每次最后两位数字在变量 2 中的一个元素是 01,该元素保留在变量 2 的列中。当变量 2 中元素的最后两位数字为 02 时,该元素转到变量 3(或者如果变量 3 不存在,则创建它)。这样,只有在必要时才会创建新变量。

标签: r string split dataframe


【解决方案1】:

这会奏效。首先让我们构建数据。

values <- paste0("0000000", 1:4)
library(data.table)
dt <- data.table(val = sample(values, 10, replace = TRUE))

一个 for 循环足以定义新列。

for(level_var in dt[, unique(val)]){
  dt[, eval(level_var) := ifelse(val == level_var, level_var, 0)]
}

【讨论】:

  • 好答案,除了你需要使用substr(eval(level_var), nchar(eval(level_var)) - 1, nchar(eval(level_var))) := ifelse(val == level_var, level_var, 0),因为看起来OP希望val = xxxxxxyy成为yy所有可能前缀的相同新列
  • 还有一些工作需要做,OP想要输出像variabl1,variable2,.....variable99
  • 我明白你的意思..什么是“level_var”?我查找了有关“data.table”包的文档,但我没有找到任何关于它的信息。感谢您的帮助!该代码还不能处理我的数据。但我正在处理它
  • for (x in y) 创建一个临时变量 x,它遍历 y 的值。所以在这种情况下,level_var 将遍历 dt[, unique(val)] 的值,这对应于表的 Variable2 列中的唯一值。
  • 啊好吧!知道了!愚蠢的问题!
【解决方案2】:

这是另一个建议。代码有点长,但我相信它可以解决问题,我希望它可以很容易理解。我假设原始数据存储在一个名为“data.dat”的制表符分隔文件中。 代码的输出存储在矩阵“new_matrix”中。这些条目是字符,但如果需要,将它们转换为整数应该不成问题。

data <- read.table('data.dat', sep='\t', header = TRUE, colClasses = "character")
var2 <- data[3]
nc <- nchar(var2[1,1])
last2 <-substr(var2[,1],nc-1,nc)
subcat <-levels(factor(last2))
mrows <- nrow(data)
mcols <- length(subcat)
varnames <-paste0("Variable",as.character(c(1:(mcols+1))))
new_matrix <- matrix(paste(replicate(nc,"0"),collapse=""),nrow=mrows,ncol=mcols+2)
colnames(new_matrix) <- c("YEAR",varnames)
new_matrix[,1]<-data[,1]
new_matrix[,2]<-data[,2]
for (i in 1:mcols) {
    relevant_rows <- which(last2 == subcat[i])
    new_matrix[relevant_rows,i+2]<-data[relevant_rows,3]
}

希望这会有所帮助。

【讨论】:

    【解决方案3】:

    使用reshape2。单线解决方案。如果我们想删除 NA 值,则另起一行。

    library(reshape2)
    df <- data.frame(YEAR=c(2009,2010,2011,2009,2010,2009,2009,2010,2009),
                     Var1=c('000000','000000','000000','000000','000000','000000','100000','100000','100000'),
                     Var2=c('0000001','0000001','0000001','0000002','0000002','0000003','1000001','1000001','1000011')) 
    df <- dcast(df, YEAR + Var1 + Var2 ~ Var2, value.var = "Var2")[, -3]
    df[is.na(df)] <- 0
    

    结果:

      YEAR   Var1 0000001 0000002 0000003 1000001 1000011
    1 2009 000000 0000001       0       0       0       0
    2 2009 000000       0 0000002       0       0       0
    3 2009 000000       0       0 0000003       0       0
    4 2009 100000       0       0       0 1000001       0
    5 2009 100000       0       0       0       0 1000011
    6 2010 000000 0000001       0       0       0       0
    7 2010 000000       0 0000002       0       0       0
    8 2010 100000       0       0       0 1000001       0
    9 2011 000000 0000001       0       0       0       0
    

    【讨论】:

      【解决方案4】:

      这是另一种方法。请注意,我选择将 subcat 虚拟变量制作成二进制指示变量以减少冗余:

      输入:

      data <- read.table(header=TRUE, text='
        year var1      var2
        2009 000000    00000001
        2010 000000    00000001
        2009 000000    00000002
        2010 000000    00000002
        2009 000000    00000003
        2009 100000    10000001
        2009 100000    10000004
        2010 100000    10000010                 
      ', colClasses = c('character', 'character', 'character'))
      

      简化 var2 列:

      subCat <- function(s) {
        substr(s, nchar(s) - 1, nchar(s))
      }
      data$var2 <- subCat(data$var2)
      

      创建假人:

      方法一:

      t <- table(1:length(data$var2), data$var2)
      data <- cbind(data, as.data.frame.matrix(t))
      data$var2 <- NULL
      

      输出:

       year   var1 01 02 03 04 10
      1 2009 000000  1  0  0  0  0
      2 2010 000000  1  0  0  0  0
      3 2009 000000  0  1  0  0  0
      4 2010 000000  0  1  0  0  0
      5 2009 000000  0  0  1  0  0
      6 2009 100000  1  0  0  0  0
      7 2009 100000  0  0  0  1  0
      8 2010 100000  0  0  0  0  1
      

      ================================================ =============

      方法二:

      library(dummies)
      data$var2 <- subCat(data$var2)
      data3 <- cbind(data, dummy(data$var2))
      data3$var2 = NULL
      

      输出:

        year   var1 data01 data02 data03 data04 data10
      1 2009 000000      1      0      0      0      0
      2 2010 000000      1      0      0      0      0
      3 2009 000000      0      1      0      0      0
      4 2010 000000      0      1      0      0      0
      5 2009 000000      0      0      1      0      0
      6 2009 100000      1      0      0      0      0
      7 2009 100000      0      0      0      1      0
      8 2010 100000      0      0      0      0      1
      

      ================================================ =============

      方法三:

      dummies <- sapply(unique(data$var2), function(x) as.numeric(data$var2 == x))
      data <- cbind(data, dummies)
      data$var2 = NULL
      

      输出:

        year   var1 X01 X02 X03 X04 X10
      1 2009 000000   1   0   0   0   0
      2 2010 000000   1   0   0   0   0
      3 2009 000000   0   1   0   0   0
      4 2010 000000   0   1   0   0   0
      5 2009 000000   0   0   1   0   0
      6 2009 100000   1   0   0   0   0
      7 2009 100000   0   0   0   1   0
      8 2010 100000   0   0   0   0   1
      

      【讨论】:

        【解决方案5】:
        library(dplyr)
        library(reshape2)
        df <- data.frame(YEAR=c(2009,2010,2011,2009,2010,2009,2009,2010,2009),
                                 Var1=c('000000','000000','000000','000000','000000','000000','100000','100000','100000'),
                                 Var2=c('0000001','0000001','0000001','0000002','0000002','0000003','1000001','1000001','1000011'))
        
        df <- mutate(df, tag=paste(YEAR, Var1, Var2, sep='-'))
        df <- dcast(df, YEAR + Var1 + tag ~ Var2, fun.aggregate = NULL)
        df$tag <- NULL
        df <- apply(df, 2, function(x) sub('^(.*)-(.*)-', '', x))
        df[is.na(df)] <- 0
        df <- as.data.frame(df)
        

        输出:

          YEAR   Var1 0000001 0000002 0000003 1000001 1000011
        1 2009 000000 0000001       0       0       0       0
        2 2009 000000       0 0000002       0       0       0
        3 2009 000000       0       0 0000003       0       0
        4 2009 100000       0       0       0 1000001       0
        5 2009 100000       0       0       0       0 1000011
        6 2010 000000 0000001       0       0       0       0
        7 2010 000000       0 0000002       0       0       0
        8 2010 100000       0       0       0 1000001       0
        9 2011 000000 0000001       0       0       0       0
        

        【讨论】:

          【解决方案6】:

          感谢您提供所有这些答案。我通过结合 Michele Usuelli 的答案和他对 Synergist 答案的评论找到了解决方案。我还了解了有关 data.table 的更多信息

          NbTabelle <- data.table(val=Netz)
          attach(NbTabelle)
          for(level_var in namesvec){
          NbTabelle[, eval(level_var) := ifelse(substr(eval(val), 7, 8) == level_var, val, 0)]
          }
          

          其中 namesvec 是我从之前生成的表中创建的变量名称向量,变量 val 除外。 我很欣赏 Synergist 代码的通用性,但出于我的目的,我只需要最后两位数。

          【讨论】:

            猜你喜欢
            • 2014-12-25
            • 2018-05-13
            • 2020-04-25
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多