【问题标题】:Trying to extract portion of csv to numpy array试图将部分 csv 提取到 numpy 数组
【发布时间】:2016-12-02 07:12:51
【问题描述】:

我已经解决这个问题几天并尝试了几种不同的方法,但我似乎无法完全正确。这是我的 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

我想将数字提取为二维数组,我希望对其进行一些数学运算。但是,在我需要忽略之前,我已经有了这些文本字段。此外,有些行不会有所有列的数字,但是一旦数字开始,它们就会向右连续(即,有些行的前几列有空项目),并且每行可能不同。此外,真实数据集有数百行数十列

这是我尝试过的一些:

    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)

再次感谢大家的帮助

【问题讨论】:

    标签: python csv numpy


    【解决方案1】:

    使用您的样本,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')])
    

    这是一个一维结构化数组;您按字段名称访问列(此处源自您的标题行)

    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(或连接)要好。

    【讨论】:

    • 我确实采用了这个解决方案,因为它符合我的大部分需求。我也会发布我最终使用的内容
    【解决方案2】:

    如果——这是一个很大的如果(我的孩子)——你可以使用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 名称 城市 州 1996-04 1996-05 1996-06 1996-07 0 鲍勃波特兰 OR 100000.0 120000.0 140000 160000 1 彼得旧金山 CA NaN NaN 440000 500000

    如你所说,将其归零:

    df = df.fillna(0)
    

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

    >>> df 名称 城市 州 1996-04 1996-05 1996-06 1996-07 0 鲍勃波特兰 OR 100000.0 120000.0 140000 160000 1 彼得旧金山 CA 0.0 0.0 440000 500000

    【讨论】:

    • 适合工作的正确工具。 Numpy 很棒,但它不能处理异构(不同)数据类型。
    • numpy 可以处理异构数据类型 - 使用结构化数组。人们一直使用genfromtxt。很多关于这个的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-07
    • 1970-01-01
    • 2016-12-09
    • 2019-12-01
    • 1970-01-01
    • 2015-08-03
    • 1970-01-01
    相关资源
    最近更新 更多