读取选项卡将csv分隔为具有不同数据类型的numpy数组

时间:2016-10-22 13:23:09

标签: python arrays csv numpy

我有一个制表符分隔的csv数据集如下:

1       2       3       4       5       6       [0, 1, 2, 3, 4, 5]
3       1       2       6       4       5       [2, 0, 1, 5, 3, 4]
7       8       9       10      11      6       [0, 1, 2, 3, 4, 5]
10      11      9       8       7       6       [3, 4, 2, 1, 0, 5]
12      13      4       14      15      6       [0, 1, 2, 3, 4, 5]
13      4       14      12      15      6       [1, 2, 3, 0, 4, 5]
16      17      18      19      20      6       [0, 1, 2, 3, 4, 5]
6       18      20      17      16      19      [5, 2, 4, 1, 0, 3]
7       21      22      23      24      6       [0, 1, 2, 3, 4, 5]
23      6       21      7       22      24      [3, 5, 1, 0, 2, 4]
25      7       21      22      23      6       [0, 1, 2, 3, 4, 5]
6       21      7       22      25      23      [5, 2, 1, 3, 0, 4]
16      26      3       27      28      6       [0, 1, 2, 3, 4, 5]
26      6       27      3       28      16      [1, 5, 3, 2, 4, 0]
7       29      24      30      31      6       [0, 1, 2, 3, 4, 5]
30      24      6       7       29      31      [3, 2, 5, 0, 1, 4]
32      33      13      34      35      36      [0, 1, 2, 3, 4, 5]
34      32      36      35      13      33      [3, 0, 5, 4, 2, 1]
7       37      38      39      40      6       [0, 1, 2, 3, 4, 5]
39      38      40      6       37      7       [3, 2, 4, 5, 1, 0]
7       41      42      43      44      6       [0, 1, 2, 3, 4, 5]
41      6       44      43      42      7       [1, 5, 4, 3, 2, 0]
7       45      46      47      48      6       [0, 1, 2, 3, 4, 5]
6       47      45      7       46      48      [5, 3, 1, 0, 2, 4]
49      2       50      51      52      6       [0, 1, 2, 3, 4, 5]

当我想将这样的csv文件导入numpy数组时,如下所示;

dataset = numpy.loadtxt('dataset/demo_dataset.csv', delimiter='\t', dtype='str')

我获得了一个(25,)形状的numpy数组。

我想将这个csv文件导入两个名为X和Y的numpy数组。

X将包含前6列,Y将包括最后一列作为列表值,而不是str。

我该如何管理?

3 个答案:

答案 0 :(得分:3)

我设法通过自定义方法实现了这一目标:

import numpy

with open('dataset/demo_dataset.csv', 'r') as fin:
    lines = fin.readlines()
    # remove '\n' characters
    clean_lines = [l.strip('\n') for l in lines]
    # split on tab so that we get lists from strings
    A = [cl.split('\t') for cl in clean_lines]
    # get lists of ints instead of lists of strings
    X = [map(int, row[0:6]) for row in A]
    # last column in Y
    Y = [row[6] for row in A]

    # convert string to int values
    for i in xrange(len(Y)):
        Y[i] = map(int, Y[i].strip('[]').split(','))

答案 1 :(得分:2)

使用genfromtxt的一些选项:

In [1047]: txt=b"""7\t8\t9\t10\t11\t6\t [0, 1, 2, 3, 4, 5]"""
In [1048]: txt=[txt,txt,txt]
In [1049]: txt
Out[1049]: 
[b'7\t8\t9\t10\t11\t6\t [0, 1, 2, 3, 4, 5]',
 b'7\t8\t9\t10\t11\t6\t [0, 1, 2, 3, 4, 5]',
 b'7\t8\t9\t10\t11\t6\t [0, 1, 2, 3, 4, 5]']

加载为默认浮点数 - 最后一列为nan

In [1050]: np.genfromtxt(txt,delimiter='\t')
Out[1050]: 
array([[  7.,   8.,   9.,  10.,  11.,   6.,  nan],
       [  7.,   8.,   9.,  10.,  11.,   6.,  nan],
       [  7.,   8.,   9.,  10.,  11.,   6.,  nan]])

作为字符串

In [1051]: np.genfromtxt(txt,delimiter='\t',dtype='str')
Out[1051]: 
array([['7', '8', '9', '10', '11', '6', ' [0, 1, 2, 3, 4, 5]'],
       ['7', '8', '9', '10', '11', '6', ' [0, 1, 2, 3, 4, 5]'],
       ['7', '8', '9', '10', '11', '6', ' [0, 1, 2, 3, 4, 5]']], 
      dtype='<U19')

让它决定最佳拟合 - 结果是一个结构化数组,带有int字段和一个字符串字段。

In [1052]: np.genfromtxt(txt,delimiter='\t',dtype=None)
Out[1052]: 
array([(7, 8, 9, 10, 11, 6, b' [0, 1, 2, 3, 4, 5]'),
       (7, 8, 9, 10, 11, 6, b' [0, 1, 2, 3, 4, 5]'),
       (7, 8, 9, 10, 11, 6, b' [0, 1, 2, 3, 4, 5]')], 
      dtype=[('f0', '<i4'), ('f1', '<i4'), ('f2', '<i4'), ('f3', '<i4'), ('f4', '<i4'), ('f5', '<i4'), ('f6', 'S19')])
In [1053]: _['f6']
Out[1053]: 
array([b' [0, 1, 2, 3, 4, 5]', b' [0, 1, 2, 3, 4, 5]',
       b' [0, 1, 2, 3, 4, 5]'], 
      dtype='|S19')

优化dtype - 一个字段有6列,另一个字符串:

In [1055]: np.genfromtxt(txt,delimiter='\t',dtype='6int,S20')
Out[1055]: 
array([([7, 8, 9, 10, 11, 6], b' [0, 1, 2, 3, 4, 5]'),
       ([7, 8, 9, 10, 11, 6], b' [0, 1, 2, 3, 4, 5]'),
       ([7, 8, 9, 10, 11, 6], b' [0, 1, 2, 3, 4, 5]')], 
      dtype=[('f0', '<i4', (6,)), ('f1', 'S20')])

第一个字段是您想要的X;最后一个字段中的字符串需要进一步处理(根据您的其他问题):

In [1060]: _['f0']
Out[1060]: 
array([[ 7,  8,  9, 10, 11,  6],
       [ 7,  8,  9, 10, 11,  6],
       [ 7,  8,  9, 10, 11,  6]])
In [1061]: __['f1']
Out[1061]: 
array([b' [0, 1, 2, 3, 4, 5]', b' [0, 1, 2, 3, 4, 5]',
       b' [0, 1, 2, 3, 4, 5]'], 

最后一个字段可以@chefarov转换为Y变量。

想想,我可以通过另一次调用genfromtxt来处理该字符串字段。我仍然需要删除[]

In [1101]: data=np.genfromtxt(txt,delimiter='\t',dtype='6int,S20')
In [1102]: data['f1']
Out[1102]: 
array([b'[0, 1, 2, 3, 4, 5]', b'[0, 1, 2, 3, 4, 5]', b'[0, 1, 2, 3, 4, 5]'], 
      dtype='|S20')
In [1103]: np.genfromtxt([l.strip(b'[]') for l in data['f1']],delimiter=',',dtype=int)
Out[1103]: 
array([[0, 1, 2, 3, 4, 5],
       [0, 1, 2, 3, 4, 5],
       [0, 1, 2, 3, 4, 5]])

我建议,在其他情况下,预处理行以删除引号,括号和问题分隔符。 genfromtxt接受来自其中的任何内容的输入。但在这种情况下,所需的处理大部分是@chefarov建议的内容 - 减去int次转化。

genfromtxt也接受转换器,但我在其他问题中发现转换器无法将一个字段更改为多个字段。

同样genfromtxt遍历文件行,并对每个文件行进行解码并收集列表中的值。因此,定制阅读器没有任何速度优势。

答案 2 :(得分:1)

如果你使用pandas,有一种(可以说)更简单的方法来读取数据。首先,可以构造一个pandas.DataFrame实例,我们可以将自定义函数应用到它的最后一列将字符串元素转换为np.ndarray类型:

import pandas as pd
import numpy as np

df = pd.read_table('dataset/demo_dataset.csv', delimiter='\t', names='abcdefg')
convert = lambda a: np.fromstring(a[1:-1], count = a.count(',') + 1, sep = ', ', dtype=int)
df.g = df.g.apply(convert)

构建混合数据帧后,XY可以简单的方式提取为数组:

X = df.values[:, :-1].astype(int)
Y = np.vstack(df.values[:, -1])