对 data.table 的每一列进行操作

Operation on each column of 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 的初学者):

File "/grid/6/hadoop/yarn/local/usercache/Z076156/appcache/application_1438295298158_169576/container_1438295298158_169576_01_000003/pyspark.zip/pyspark/mllib/util.py", line 45, in _parse_libsvm_line label = float(items[0]) ValueError: could not convert string to float: "505",0,"17661674","MULTI-COLORED","0","75",2,131,"2","",0,"XS","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(所有字符串列的一个映射(字符串 -> 某个数字)之一)

你可以试试:

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)