对每列data.table进行操作

时间:2015-09-23 18:34:21

标签: r data.table

我有一个表格的data.table:

d1 <- data.table(read.csv(header=TRUE, file=textConnection("x1,y1,z1
string1,string2,1
string3,string1,2
string3,string5,3")))

我正在尝试将此数据转换为Spark中的用法。似乎Spark没有把字符串作为输入或尝试转换它(我在Spark中非常初学者):

  

文件   &#34; /grid/6/hadoop/yarn/local/usercache/Z076156/appcache/application_1438295298158_169576/container_1438295298158_169576_01_000003/pyspark.zip/pyspark/mllib/util.py" ;,   第45行,在_parse_libsvm_line中       label = float(items [0])ValueError:无法将字符串转换为float:   &#34; 505&#34;,0,&#34; 17661674&#34;&#34;多色&#34;&#34; 0&#34;&#34; 75&#34;,2131 &#34; 2&#34;&#34;&#34;,0,&#34; XS&#34;&#34; 5.10

所以我试图将所有字符串转换为R中的数字因子。这是一个简单的函数,我根据我成功转换只有一列来编写:

string2num <- function(d,a){
  l<-unique(c(as.character(d$a)))
  return(as.numeric(factor(d$a, levels=l)))
}

但是我无法将其应用于表的多个字符串列(由于函数中的原子向量引用)。目前正在编写简单的代码片段和调试但不成功。我期待一种形式的解决方案:

for(i in colnames(d1)){
  if(is.character(d1$i))
    string2num(d1,i)
}

或:

d1[,lapply(.SD, string2num),.SDcols=is.character(.SD)]

或:

do.call(rbind(lapply(d1[,sapply(d1,is.character)],string2num)))

或者我可能没有任何正确解决方案的线索。预期的产出将是以下形式:

  x1 y1 z1
1:  1  1  1
2:  2  2  2
3:  2  3  3

请注意,在x1列中,string3的两个实例都为数字1(所有字符串列的一个映射(字符串 - >某些数字)之一)

1 个答案:

答案 0 :(得分:3)

你可以尝试:

indx <- which(sapply(d1, is.character))
d1[, (indx) := lapply(.SD, as.factor), .SDcols = indx
   ][, (indx) := lapply(.SD, as.integer), .SDcols = indx]

或@Frank提出的所有内容:

d1[, (indx) := lapply(.SD, function(x) as.integer(as.factor(x))), .SDcols=indx]

这给出了:

> d1
   x1 y1 z1
1:  1  2  1
2:  2  1  2
3:  2  3  3

使用过的数据:

d1 <- fread("x1,y1,z1
string1,string2,1
string3,string1,2
string3,string5,3", header=TRUE)