试图将部分csv提取到numpy数组

时间:2016-07-28 04:30:10

标签: python csv numpy

我已经在这个问题上待了几天,尝试了几种不同的方法,但我似乎无法做到这一点。这是我的csv数据文件的简化版本:testme.csv

   "Name", "City", "State", "1996-04", "1996-05", "1996-06", "1996-07"
   "Bob", "Portland", "OR", 100000, 120000, 140000, 160000
   "Sally", "Eugene", "OR", 50000, 75000, 80000, 90000
   "Peter", "San Francisco", "CA", , , 440000, 500000

我想将数字提取为2D数组,我希望对其进行数学处理。但是我之前有这些文本字段,我需要忽略。此外,某些行不会包含所有列的数字,但一旦数字开始,它们就会连续向右(即某些行的前几列有空项),每行可能不同。此外,真实数据集有数百行和数十列

这是我尝试过的一些内容:

    import csv
    import numpy as np

    filename = "testme.csv"

    ifile = open(filename, 'r')
    header1 = ifile.readline()

    reader = csv.reader(ifile)
    A = np.array([]).reshape(0, 4)

    for row in reader:
        print row
        print row[3:]
        A = np.vstack([A, row[3:]])

    print A

然后我明白了:

  ['Bob', ' "Portland"', ' "OR"', ' 100000', ' 120000', ' 140000', ' 160000']
    [' 100000', ' 120000', ' 140000', ' 160000']
    ['Sally', ' "Eugene"', ' "OR"', ' 50000', ' 75000', ' 80000', ' 90000']
    [' 50000', ' 75000', ' 80000', ' 90000']
    ['Peter', ' "San Francisco"', ' "CA"', ' ', ' ', ' 440000', ' 500000']
    [' ', ' ', ' 440000', ' 500000']
    [[' 100000' ' 120000' ' 140000' ' 160000']
     [' 50000' ' 75000' ' 80000' ' 90000']
     [' ' ' ' ' 440000' ' 500000']]

我很接近,但元素现在都是文字字符串。有没有更简单的方法来做到这一点并取代数字或我知道经历这个并将每个元素转换为数字?而空元素我可以将它们钳制到零而受益。

提前感谢您的建议和帮助!

亚伦

更新(8/1/16) 我确实选择了genfromtxt方法,因为它匹配了我需要的东西。这是后人和其他人的结果

    import csv
    import numpy as np

    NumIgnoreFirstCols = 3
    filename = "testme2.csv"

    ifile = open(filename, 'r')
    reader = csv.reader(ifile)
    header1 = next(reader)
    numcols = len(header1)
    #Find number of cols for usecol in genfromtxt
    print("numcols", numcols)
    ifile.close()

    print(range(NumIgnoreFirstCols, numcols))

    aMatrix = np.genfromtxt(filename, skip_header=1, delimiter=',', usecols=range(NumIgnoreFirstCols,numcols), dtype=int)

    print aMatrix

    normalizedMatrix = np.where(aMatrix<0, 0, aMatrix)
    print(normalizedMatrix)

    minValue = np.amin(normalizedMatrix)
    maxValue = np.amax(normalizedMatrix)
    print (minValue, maxValue)

再次感谢所有帮助

2 个答案:

答案 0 :(得分:2)

使用您的示例,numpy genfromtxt有效:

In [166]: np.genfromtxt('stack38627130.csv',names=True,delimiter=',',dtype=None)

Out[166]: 
array([(b'"Bob"', b' "Portland"', b' "OR"', 100000, 120000, 140000, 160000),
       (b'"Sally"', b' "Eugene"', b' "OR"', 50000, 75000, 80000, 90000),
       (b'"Peter"', b' "San Francisco"', b' "CA"', -1, -1, 440000, 500000)], 
      dtype=[('Name', 'S7'), ('City', 'S16'), ('State', 'S5'), ('199604', '<i4'), ('199605', '<i4'), ('199606', '<i4'), ('199607', '<i4')])

这是一个1d结构化数组;您可以按字段名称访问列(此处从标题行派生)

In [167]: data=_
In [168]: data['199604']
Out[168]: array([100000,  50000,     -1])
In [169]: data['199607']
Out[169]: array([160000,  90000, 500000])

缺少的字段填充-1。我认为可以改变。

如果您不喜欢推断的字段名,还有其他参数可用于设置字段名称。

读取可以限制在数字列中;不同的填充取决于dtype

In [171]: np.genfromtxt('stack38627130.csv',skip_header=1,delimiter=',',usecols=
     ...: [3,4,5,6])
Out[171]: 
array([[ 100000.,  120000.,  140000.,  160000.],
       [  50000.,   75000.,   80000.,   90000.],
       [     nan,      nan,  440000.,  500000.]])
In [172]: np.genfromtxt('stack38627130.csv',skip_header=1,delimiter=',',usecols=
     ...: [3,4,5,6],dtype=int)
Out[172]: 
array([[100000, 120000, 140000, 160000],
       [ 50000,  75000,  80000,  90000],
       [    -1,     -1, 440000, 500000]])

现在我们得到一个二维数组。

我相信pandas可以更好地处理丢失的字段,但只要这些字段标有分隔符,genfromtxt就不会有问题。

genfromtxt大致如下:

result = []
for row in reader:
    data = row[3:]
    data = [float(x) for x in data]
    result.append(data)
result = np.array(result)
如果所有字符串都正确转换,

np.array可以进行浮点转换;它不处理空的或nan。通常收集值列表优于重复vstack(或连接)。

答案 1 :(得分:1)

如果 - 这是一个很大的if(我小子) - 你可以使用pandas

from StringIO import StringIO
s = StringIO('''   "Name", "City", "State", "1996-04", "1996-05", "1996-06", "1996-07"
                   "Bob", "Portland", "OR", 100000, 120000, 140000, 160000
                   "Peter", "San Francisco", "CA", , , 440000, 500000   ''')
df = pd.read_csv(s,skipinitialspace=True)

到达那里......

>>> df
    Name           City State   1996-04   1996-05  1996-06  1996-07
0    Bob       Portland    OR  100000.0  120000.0   140000   160000
1  Peter  San Francisco    CA       NaN       NaN   440000   500000

如你所说:

df = df.fillna(0)

我认为这是你想要的最终结果:

>>> df
    Name           City State   1996-04   1996-05  1996-06  1996-07
0    Bob       Portland    OR  100000.0  120000.0   140000   160000
1  Peter  San Francisco    CA       0.0       0.0   440000   500000