以libsvm格式读/写数据

sds*_*sds 14 r libsvm

如何读/写libsvm数据R

libsvm格式是这样稀疏数据

<class/target>[ <attribute number>:<attribute value>]*
Run Code Online (Sandbox Code Playgroud)

(参见压缩行存储(CRS))例如,

1 10:3.4 123:0.5 34567:0.231
0.2 22:1 456:03
Run Code Online (Sandbox Code Playgroud)

我相信我可以自己鞭打一些东西,但我宁愿使用现成的东西.但是,Rforeign似乎没有提供必要的功能.

sds*_*sds 14

e1071 现成的:

install.packages("e1071")
library(e1071)
read.matrix.csr(...)
write.matrix.csr(...)
Run Code Online (Sandbox Code Playgroud)

注意:它是在R,而不是在C,所以它是狗慢.

它甚至有一个特殊的小插图支持向量机 - 包e1071中的libsvm接口.

r.vw 与...捆绑在一起 vowpal_wabbit

注意:它是在R,而不是在C,所以它是狗慢.


小智 10

我一直在使用zygmuntz解决方案在一个拥有25k观测值(行)的数据集上运行了近5个小时.它做了3k-ish行.花了这么长时间我在此期间编写了这个(基于zygmuntz的代码):

require(Matrix)
read.libsvm = function( filename ) {
  content = readLines( filename )
  num_lines = length( content )
  tomakemat = cbind(1:num_lines, -1, substr(content,1,1))

  # loop over lines
  makemat = rbind(tomakemat,
  do.call(rbind, 
    lapply(1:num_lines, function(i){
       # split by spaces, remove lines
           line = as.vector( strsplit( content[i], ' ' )[[1]])
           cbind(i, t(simplify2array(strsplit(line[-1],
                          ':'))))   
})))
class(makemat) = "numeric"

#browser()
yx = sparseMatrix(i = makemat[,1], 
              j = makemat[,2]+2, 
          x = makemat[,3])
return( yx )
}
Run Code Online (Sandbox Code Playgroud)

这可以在同一台机器上运行几分钟(zygmuntz解决方案也可能存在内存问题,不确定).希望这可以帮助任何有同样问题的人.

请记住,如果你需要在R中做大计算,VECTORIZE!

编辑:修复了我今天早上发现的索引错误.

  • 很抱歉回复这样的旧帖子,但尼古拉斯·麦卡锡(Nicholas McCarthy),您的函数似乎没有提供正确的格式,原因是:'data2 &lt;-Matrix(c(1(35,35,2,241,11,1,23, 31),sparse = TRUE,nrow = 3)',它在第一行给出:'1 2:2 1 3:1',但是第二行“ 1”不应该出现吗? (2认同)

Mic*_*ico 7

我想出了自己的临时解决方案,利用了一些data.table实用程序,

它在我发现的测试数据集(波士顿住房数据)上几乎很快就运行了。

将其转换为 a data.table(与解正交,但在此处添加以方便重现):

library(data.table)
x = fread("/media/data_drive/housing.data.fw",
          sep = "\n", header = FALSE)
#usually fixed-width conversion is harder, but everything here is numeric
columns =  c("CRIM", "ZN", "INDUS", "CHAS",
             "NOX", "RM", "AGE", "DIS", "RAD", 
             "TAX", "PTRATIO", "B", "LSTAT", "MEDV")
DT = with(x, fread(paste(gsub("\\s+", "\t", V1), collapse = "\n"),
                   header = FALSE, sep = "\t",
                   col.names = columns))
Run Code Online (Sandbox Code Playgroud)

这里是:

DT[ , fwrite(as.data.table(paste0(
  MEDV, " | ", sapply(transpose(lapply(
    names(.SD), function(jj)
      paste0(jj, ":", get(jj)))),
    paste, collapse = " "))), 
  "/path/to/output", col.names = FALSE, quote = FALSE),
  .SDcols = !"MEDV"]
#what gets sent to as.data.table:
#[1] "24 | CRIM:0.00632 ZN:18 INDUS:2.31 CHAS:0 NOX:0.538 RM:6.575 
#  AGE:65.2 DIS:4.09 RAD:1 TAX:296 PTRATIO:15.3 B:396.9 LSTAT:4.98 MEDV:24"      
#[2] "21.6 | CRIM:0.02731 ZN:0 INDUS:7.07 CHAS:0 NOX:0.469 RM:6.421 
#  AGE:78.9 DIS:4.9671 RAD:2 TAX:242 PTRATIO:17.8 B:396.9 LSTAT:9.14 MEDV:21.6"
# ...
Run Code Online (Sandbox Code Playgroud)

可能是一个更好的方式来获得这种理解fwrite不是as.data.table,但我不能想到一个(直到setDT作品的载体)。

我复制了这个来测试它在更大的数据集上的性能(只是炸毁当前的数据集):

DT2 = rbindlist(replicate(1000, DT, simplify = FALSE))
Run Code Online (Sandbox Code Playgroud)

与此处报告的某些时间相比,该操作非常快(我还没有费心直接进行比较):

system.time(.)
#    user  system elapsed 
#   8.392   0.000   8.385 
Run Code Online (Sandbox Code Playgroud)

我还测试了使用writeLines而不是fwrite,但后者更好。


我再次查看,发现可能需要一段时间才能弄清楚发生了什么。也许magrittr-piped 版本会更容易遵循:

DT[ , 
    #1) prepend each column's values with the column name
    lapply(names(.SD), function(jj)
      paste0(jj, ":", get(jj))) %>%
      #2) transpose this list (using data.table's fast tool)
      #   (was column-wise, now row-wise)
      #3) concatenate columns, separated by " "
      transpose %>% sapply(paste, collapse = " ") %>%
      #4) prepend each row with the target value
      #   (with Vowpal Wabbit in mind, separate with a pipe)
      paste0(MEDV, " | ", .) %>%
      #5) convert this to a data.table to use fwrite
      as.data.table %>%
      #6) fwrite it; exclude nonsense column name,
      #   and force quotes off
      fwrite("/path/to/data", 
             col.names = FALSE, quote = FALSE),
  .SDcols = !"MEDV"]
Run Code Online (Sandbox Code Playgroud)

读取此类文件要容易得多**

#quickly read data; don't split within lines
x = fread("/path/to/data", sep = "\n", header = FALSE)

#tstrsplit is transpose(strsplit(.))
dt1 = x[ , tstrsplit(V1, split = "[| :]+")]

#even columns have variable names
nms = c("target_name", 
        unlist(dt1[1L, seq(2L, ncol(dt1), by = 2L), 
                   with = FALSE]))

#odd columns have values
DT = dt1[ , seq(1L, ncol(dt1), by = 2L), with = FALSE]
#add meaningful names
setnames(DT, nms)
Run Code Online (Sandbox Code Playgroud)

**这不适用于“参差不齐”/稀疏输入数据。我认为没有办法将其扩展到在这种情况下工作。