【问题标题】:R split data to frequency [duplicate]R将数据拆分为频率[重复]
【发布时间】:2016-02-06 05:53:40
【问题描述】:

我有一个这样的数据集,其中有一个包含逗号分隔代码的变量(“item”):

id  item
1    102, 103,401,
2    108,102,301
3    103, 108 , 405, 505, 708

对于每个 id,我想获取每个单独项目的频率,如下所示:

id  102  103   104   108  301 401 ...
1    1    1                    1
2    1                 1    1
3         1            1

我该怎么做?

【问题讨论】:

    标签: r


    【解决方案1】:

    我们可以使用来自qdapToolsmtabulate 来做到这一点

    library(qdapTools)
    cbind(dat['id'], mtabulate(strsplit(dat$item, '\\s*,\\s*')))
    #  id 102 103 108 301 401 405 505 708
    #1  1   1   1   0   0   1   0   0   0
    #2  2   1   0   1   1   0   0   0   0
    #3  3   0   1   1   0   0   1   1   1
    

    注意:数据取自 @thelatemail 的帖子。


    或者其他选项(如果我们需要sparseMatrix

    library(Matrix)
    #split the 'item' column to `list`
    lst <- strsplit(dat$item, '\\s*,\\s*')
    #get the `unique` elements after `unlist`ing.
    Un1 <- sort(unique(unlist(lst)))
    #create a `sparseMatrix` by specifying the row
    #column index along with dim names (if needed)
    sM <-  sparseMatrix(rep(dat$id, lengths(lst)), 
                match(unlist(lst), Un1), x= 1, 
                 dimnames=list(dat$id, Un1))
    sM
    #    3 x 8 sparse Matrix of class "dgCMatrix"
    #   102 103 108 301 401 405 505 708
    #1   1   1   .   .   1   .   .   .
    #2   1   .   1   1   .   .   .   .
    #3   .   1   1   .   .   1   1   1
    

    可以通过as.matrix包裹转换为matrix

    as.matrix(sM)
    #   102 103 108 301 401 405 505 708
    #1   1   1   0   0   1   0   0   0
    #2   1   0   1   1   0   0   0   0
    #3   0   1   1   0   0   1   1   1
    

    【讨论】:

    • 谢谢,但是当我运行代码时 q
    • @user2609451 在我从 thelatemail 的帖子中获取的数据集中,“项目”列是 character。如果您有 factor 类,请将其转换为 character 并且它应该可以正常工作(因为 strsplit 需要 character 类列)即。 mtabulate(strsplit(as.character(text$item),...
    • 对不起,从我的 url 数据开始
    • 我已经解决了上述问题,但是,当运行函数 sM 时,我在 i + (!(m.i || i1)) 中收到此错误:二进制运算符的非数字参数跨度>
    • @user2609451 正如我上面提到的,我使用的是 thelatemail 的数据,它运行良好。关于$算子的问题,看看你有没有matrix作为数据集。
    【解决方案2】:

    使用strsplit,然后利用factor 确保包含所有列数。

    spl <- strsplit(dat$item,"\\s*,\\s*")
    ulevs <- sort(unique(unlist(spl)))
    tab <- t(vapply(
      spl, 
      function(x) table(factor(x,levels=ulevs)),
      FUN.VALUE=numeric(length(ulevs))
    ))
    cbind(dat["id"],tab)
    
    #  id 102 103 108 301 401 405 505 708
    #1  1   1   1   0   0   1   0   0   0
    #2  2   1   0   1   1   0   0   0   0
    #3  3   0   1   1   0   0   1   1   1
    

    使用的数据:

    dat <- read.table(text="id;item
    1;102, 103,401,
    2;108,102,301
    3;103, 108 , 405, 505, 708",header=TRUE,sep=";",stringsAsFactors=FALSE)
    

    【讨论】:

    • 或者修改你的方法是table(stack(setNames(spl, dat$id))[2:1])
    • 谢谢您..但是当我运行第一行时,我收到此消息 Error in dat$item : $ operator is invalid for atomic vectors。我已经使用这个命令 dati
    【解决方案3】:

    您可以使用strsplit 函数执行此操作。以下是我的解决方案

    library(data.table)
    id <- c(1:3)
    item <- c("102, 103,401",  "108,102,301", "103, 108 , 405, 505, 708")
    dataT <- data.table(id, item)
    
    reqCol <- unlist(strsplit(dataT$item, split=","))
    reqCol <- gsub(" ", "", reqCol)
    reqCol <-  unique(reqCol)
    reqColNames <- paste0("Col_", reqCol)
    
    for(i in 1:length(reqCol)){
        expr1 <- parse(text = paste0(reqColNames[i], ":=0"))
        expr2 <- parse(text = paste0(reqColNames[i], ":=1"))
        dataT[, eval(expr1)]
        rowIndex <- grep(reqCol[i], dataT$item)
        dataT[rowIndex, eval(expr2)] 
    }
    

    我使用了 data.table 而不是 data.frame,因为与 data.frame 相比,data.table 非常快。

    【讨论】:

    • 我想知道,是否可以使用矢量化代码删除 for 循环..
    • 非常感谢...但是,当我运行此命令时 reqCol
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-24
    • 2013-09-24
    • 1970-01-01
    • 2020-03-06
    • 1970-01-01
    相关资源
    最近更新 更多