Spark MLlib 的官方例子里面提供的数据大部分是 libsvm 格式的。这其实是一种非常蛋疼的文件格式,和常见的二维表格形式相去甚远,下图是里面的一个例子:

完整代码

libsvm 文件的基本格式如下:

<label> <index1>:<value1> <index2>:<value2>…

label 为类别标识,index 为特征序号,value 为特征取值。如上图中第一行中 0 为标签,128:51 表示第 128 个特征取值为 51 。

Spark 固然提供了读取 libsvm 文件的API,然而如果想把这些数据放到别的库 (比如scikit-learn) 中使用,就不得不面临一个格式转换的问题了。由于 CSV 文件是广大人民群众喜闻乐见的文件格式,因此分别用 Python 和Java 写一个程序来进行转换。我在网上查阅了一下,基本上全是 csv 转 libsvm,很少有 libsvm 转 csv 的,唯一的一个是 phraug库中的libsvm2csv.py 。但这个实现有两个缺点: 一个是需要事先指定维度; 另一个是像上图中的特征序号是 128 - 658 ,这样转换完之后 0 - 127 维的特征全为 0,就显得多余了,而比较好的做法是将全为 0 的特征列一并去除。下面是基于 Python 的实现:

import sys
import csv
import numpy as np def empty_table(input_file): # 建立空表格, 维数为原数据集中最大特征维数
max_feature = 0
count = 0
with open(input_file, 'r', newline='') as f:
reader = csv.reader(f, delimiter=" ")
for line in reader:
count += 1
for i in line:
num = int(i.split(":")[0])
if num > max_feature:
max_feature = num return np.zeros((count, max_feature + 1)) def write(input_file, output_file, table):
with open(input_file, 'r', newline='') as f:
reader = csv.reader(f, delimiter=" ")
for c, line in enumerate(reader):
label = line.pop(0)
table[c, 0] = label
if line[-1].strip() == '':
line.pop(-1) line = map(lambda x : tuple(x.split(":")), line)
for i, v in line:
i = int(i)
table[c, i] = v delete_col = []
for col in range(table.shape[1]):
if not any(table[:, col]):
delete_col.append(col) table = np.delete(table, delete_col, axis=1) # 删除全 0 列
with open(output_file, 'w') as f:
writer = csv.writer(f)
for line in table:
writer.writerow(line) if __name__ == "__main__":
input_file = sys.argv[1]
output_file = sys.argv[2]
table = empty_table(input_file)
write(input_file, output_file, table)

以下基于 Java 来实现,不得不说 Java 由于没有 Numpy 这类库的存在,写起来要繁琐得多。

import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; public class LibsvmToCsv {
public static void main(String[] args) throws IOException { String src = args[0];
String dest = args[1]; double[][] table = EmptyTable(src);
double[][] newcsv = NewCsv(table, src);
write(newcsv, dest);
} // 建立空表格, 维数为原数据集中最大特征维数
public static double[][] EmptyTable(String src) throws IOException {
int maxFeatures = 0, count = 0;
File f = new File(src);
BufferedReader br = new BufferedReader(new FileReader(f));
String temp = null;
while ((temp = br.readLine()) != null){
count++;
for (String pair : temp.split(" ")){
int num = Integer.parseInt(pair.split(":")[0]);
if (num > maxFeatures){
maxFeatures = num;
}
}
}
double[][] emptyTable = new double[count][maxFeatures + 1];
return emptyTable;
} public static double[][] NewCsv(double[][] newTable, String src) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(src)));
String temp = null;
int count = 0;
while ((temp = br.readLine()) != null){
String[] array = temp.split(" ");
double label = Integer.parseInt(array[0]);
for (String pair : Arrays.copyOfRange(array, 1, array.length)){
String[] pairs = pair.split(":");
int index = Integer.parseInt(pairs[0]);
double value = Double.parseDouble(pairs[1]);
newTable[count][index] = value;
}
newTable[count][0] = label;
count++;
} List<Integer> deleteCol = new ArrayList<>(); // 要删除的全 0 列
int deleteColNum = 0; coll:
for (int col = 0; col < newTable[0].length; col++){
int zeroCount = 0;
for (int row = 0; row < newTable.length; row++){
if (newTable[row][col] != 0.0){
continue coll; // 若有一个值不为 0, 继续判断下一列
} else {
zeroCount++;
}
} if (zeroCount == newTable.length){
deleteCol.add(col);
deleteColNum++;
}
} int newColNum = newTable[0].length - deleteColNum;
double[][] newCsv = new double[count][newColNum]; // 新的不带全 0 列的空表格
int newCol = 0; colll:
for (int col = 0; col < newTable[0].length; col++){
for (int dCol : deleteCol){
if (col == dCol){
continue colll;
}
} for (int row = 0; row < newTable.length; row++){
newCsv[row][newCol] = newTable[row][col];
}
newCol++;
}
return newCsv;
} public static void write(double[][] table, String path) throws FileNotFoundException {
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path)));
try{
for (double[] row : table){
int countComma = 0;
for (double c : row){
countComma ++;
bw.write(String.valueOf(c));
if (countComma <= row.length - 1){
bw.append(',');
}
}
bw.flush();
bw.newLine();
}
} catch (IOException e){
e.printStackTrace();
} finally {
try{
if (bw != null){
bw.close();
}
} catch (IOException e){
e.printStackTrace();
}
}
}
}

/

LibSVM文件转换为csv格式的更多相关文章

  1. 如何将EDI报文转换为CSV格式文件?

    如果您对EDI项目实施有一定的了解,想必您一定知道,在正式开始EDI项目实施之前,都会有EDI顾问与您接洽,沟通EDI项目需求.其中,会包含EDI通信双方使用哪种传输协议,传输的报文是符合什么标准的, ...

  2. C# 将PDF文件转换为word格式

    Pdf(Portable Document Format)意为“便携式文档格式”,是现在最流行的文件格式之一,它有很多优点如:尺寸较小.阅读方便.操作系统平台通用等,非常适合在网络上传播和使用.如今在 ...

  3. java 调用OpenOffice将word格式文件转换为pdf格式

    一:环境搭建 OpenOffice 下载地址http://www.openoffice.org/ JodConverter 下载地址http://sourceforge.net/projects/jo ...

  4. 将 Graphviz .dot 文件转换为其他格式的图像

    参考: Graphviz: How to go from .dot to a graph? 将 Graphviz .dot 文件转换为其他格式的图像 在Linux系统下,使用以下命令: dot -Tp ...

  5. PHP 将amr音频文件转换为mp3格式

    说下整体思路 1.服务器安装ffmpeg 2.使用ffmpeg -i 指令来转换amr为mp3格式(这个到时候写在PHP代码中,使用exec函数执行即可) 3.在网页端使用HTML5的audio标签来 ...

  6. excel批量转换为CSV格式,xls批量导出csv格式

    工具/原料   excel 2013 地址链接:http://pan.baidu.com/s/1c1ZABlu 密码:d3rc 方法/步骤     首选我们把需要导出为CVS的Excel文件整理集中到 ...

  7. 将dos格式文件转换为unix格式

    在windows下换行符是\r\n,表示回到行首并换到下一行 而unix系统中换行符是\n 这样就存在一个问题,在windows上的文档到了unix上可能就无法使用了 针对这个情况有几种解决办法: 1 ...

  8. 如何使用python把json文件转换为csv文件

    @ 目录 了解json整体格式 转换格式 提取key和value 使用pandas写入csv 了解json整体格式 这里有一段json格式的文件,存着全球陆地和海洋的每年异常气温(这里只选了一部分): ...

  9. 将excel2003文档文件转换为excel2007格式

    在sharepoint 2010 中,excel2007或excel 2010文档格式,支持web app 应用,能够在浏览器在线打开,查看,但excel 2003格式的文档只能用office客户端打 ...

随机推荐

  1. [BZOJ5139][Usaco2017 Dec]Greedy Gift Takers 权值线段树

    Description Farmer John's nemesis, Farmer Nhoj, has NN cows (1≤N≤10^5), conveniently numbered 1…N. T ...

  2. Python time strptime()与time strftime()

    time strftime()接收时间元组,返回表示时间的字符串. time strptime()把时间字符串,解析成一个时间元组. import time t = time.strftime('%Y ...

  3. UVa 10766 Organising the Organisation(矩阵树定理)

    https://vjudge.net/problem/UVA-10766 题意: 给出n, m, k.表示n个点,其中m条边不能直接连通,求生成树个数. 思路: 这也算个裸题,把可以连接的边连接起来, ...

  4. UVa 10340 子序列

    https://vjudge.net/problem/UVA-10340 题意: 输入两个字符串s和t,判断是否可以从t中删除0个或多个字符得到字符串s. 思路: 很水的题... #include&l ...

  5. HTML5 Plus 拍照或者相册选择图片上传

    HBuilder+HTML5 Plus+MUI实现拍照或者相册选择图片上传,利用HTML5 Plus的Camera.Gallery.IO.Storage和Uploader来实现手机APP拍照或者从相册 ...

  6. sublime+LatexTools引用参考文献

        在用sublime+LatexTools一段时间之后,发现用它来写Latex真的是非常方便,配置好TexLive之后直接CTRL+B就可以直接编译运行了,so cool!但是最近写课程论文的时 ...

  7. java中Scanner类nextInt之后用nextLine无法读取输入

    http://blog.csdn.net/wjy1090233191/article/details/42080029 这篇文章写得非常详细和准确

  8. typeof

    1.用法 typeof num typeof(num) 2.返回值    "number"."string"."boolean"." ...

  9. CCF 100012. 技能树

    100012. 技能树 思路:区间dp. 状态:dp[i][j]表示节点为i,高度小于等于j的方案数. 状态转移:dp[i][j]=∑dp[k][j-1]*dp[i-1-k][j-1]. 节点为i,高 ...

  10. Windows 环境下安装 Oracle JDK

    本页面中描述了如何在 Window 环境下安装 Oracle JDK. 我们使用的版本是 Window 10,我们需要安装的版本是 Oracle JDK 8u191. 检查当前版本 在进行新的 JDK ...