我有一个包含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
...
请建议更快更可行的代码,因为申请需要花费大量时间来提供输出
答案 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
需要花费大量时间来提供输出。所以,我做了
为了与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 |