选择具有特定值

时间:2016-05-31 07:40:58

标签: r text dplyr

我有一个包含500多个列名和567800行的数据集。每列的值都是0,1,2,3等。

我想创建一个单独的列,其中粘贴的列名不等于0。

我尝试在R中运行循环但是我没有得到理想的结果并且需要很长时间。 我的数据如下:

DOC_ID  my_name your_name his_name our_name.....546 columns
  1        0         1         0        5   
  2        5         0         2        6   
  3        0         1         5        0
  ....

所需的输出是:

DOC_ID  my_name your_name his_name our_name..     paste_column
  1        0         1         0        5       your_name our_name
  2        5         0         2        0       my_name his_name
  3        0         1         5        0       your_name his_name
  ...

请建议更快更可行的代码,因为申请需要花费大量时间来提供输出

4 个答案:

答案 0 :(得分:3)

使用基础R的一种方式,

apply(df, 1, function(i) paste(names(i[i > 0 ]), collapse = ''))

apply(df, 1, function(i) paste(names(i[i != 0 ]), collapse = ''))

答案 1 :(得分:2)

你可以试试这个

library(data.table)
library(stringr)

set.seed(1234)
nc <- 500L
nr <- 100000L

### SETTING UP DUMMY DATA
# create data.table 
dt <- data.table(id = seq_len(nr))
# make space for additional columns
alloc.col(dt, 1L + nc)
# create new columns and fill with dummy data
for (jc in seq_len(nc)) {
  set(dt, j = paste0("V", jc), value = sample(0:5, nr, replace = TRUE))
}

### PROPOSED SOLUTION
# reshape from wide to long
mt <- melt(dt, id.vars = "id")
# keep names of non zero columns
mt[value == 0, variable := ""]
# remove value column to save RAM
mt[, value := NULL]
# aggregate by id
ct <- mt[, .(nonzerocols = str_c(variable, collapse = " ")), keyby = id]
# clean up blanks
ct[, nonzerocols := str_trim(str_replace_all(nonzerocols, "[ ]{2,}", " "))]
# add new column to original data.table (merge)
dt[ct, on = "id"]

此示例包含500列x 100&#39,000行,在我的PC上耗时约12秒,需要770 MB RAM(根据tables())。因此,熔融数据的内存消耗可能是一个问题。

修改

Sotos建议使用来自基地R的apply一个聪明的单行。另一方面,OP在他的问题中声称apply需要花费大量时间来提供输出。所以,我做了

的基准测试
  1. 我的回答使用data.table和reshape
  2. 改造版本的重塑方法
  3. 索托斯&#39;使用申请
  4. 回答

    为了与Sotos的答案进行公平比较,我的答案中的最终合并将被跳过。

    reshape方法的改进版本从熔融data.table中删除所有零行。当数据中包含更多的零时,这应该变得更有效。

    reshape2 <- function(dt) {
      # reshape from wide to long
      mt <- melt(dt, id.vars = "id")
      # keep names only of non zero columns => remove rows with zeros
      mt <- mt[value != 0]
      # remove value column to save RAM
      mt[, value := NULL]
      # aggregate by id
      ct <- mt[, .(nonzerocols = str_c(variable, collapse = " ")), keyby = id]
      return(ct)
    }
    

    基准测试是在microbenchmark包的帮助下完成的:

    microbenchmark(
      r1 <- reshape1(dt),
      r2 <- reshape2(dt),
      r3 <- sotos(dt),
      times = 3)
    

    有500个cols x 100&#39,000行,结果是:

    Unit: seconds
                   expr      min       lq     mean   median       uq      max neval
     r1 <- reshape1(dt) 8.989972 9.110466 9.193764 9.230960 9.295660 9.360360     3
     r2 <- reshape2(dt) 4.727613 5.131648 5.300693 5.535683 5.587234 5.638785     3
        r3 <- sotos(dt) 7.528728 7.858817 8.020705 8.188905 8.266693 8.344480     3
    

    对于大量的列和行,改进的重塑方法显示出最佳性能。然而,索托斯&#39;简洁的单行内存在内存消耗方面更有效。我能够在我的PC上使用8 MB RAM运行500 cols x 500&#39,000行示例,这需要44秒,而我改进的重塑方法由于内存不足而失败。所以,Sotos获得了+1。

答案 2 :(得分:0)

您可能希望忽略零并将它们视为缺失值:

mytext1[mytext1==0] <- NA

然后,只需使用

运行命令
na.rm = TRUE

例如

mean(x, na.rm=TRUE)

答案 3 :(得分:0)

dt <- data.table(V1=1:5, V2=3:7, V3=7:3)

dt[ , paste_column  := paste( names( dt[,colMeans(dt>2)==T, with=F] ), collapse = ' ') ]

>    V1 V2 V3 paste_column
> 1:  1  3  7        V2 V3
> 2:  2  4  6        V2 V3
> 3:  3  5  5        V2 V3
> 4:  4  6  4        V2 V3
> 5:  5  7  3        V2 V3

这是一个可重复的例子:

│ # │ Device Name │ Platform │ Device Identifier   │ Type     │ Status    │
│ 1 │ vbox86p     │ Android  │ 192.168.56.101:5555 | Emulator │ Connected │
│ 2 │ iPhone 5    │ iOS      │ f5ae7a02a8ba77fa572 │ Device   │ Connected │
│ 3 │ iPhone 6    │ iOS      │ 03AEBB35-4EC4-4DCC  │ Emulator │ Connected |