自定义读取CSV文件(关键字可访问/自定义结构)

时间:2015-06-05 14:42:42

标签: python csv numpy matplotlib

我正在尝试执行以下操作: 我下载了一个包含过去180天银行交易的csv文件。 我想阅读这个csv文件,然后用数据做一些图。 为此,我设置了一个程序,该程序读取csv文件并通过关键字使数据可用。 例如在csv文件中有一列“Buchungstag”。 我用date关键字等替换它。

import numpy as np
import matplotlib.pylab as mpl
import csv

class finanz():

    def __init__(self):

        path = "/home/***/"
        self.dataFileName = path + "test.csv"
        self.data_read = open(self.dataFileName, 'r')
        self._columns = {}
        self._columns[0] = ["date", "Buchungstag", "", "S15"]
        self._columns[1] = ["value", "Umsatz", "Euro", "f8"]
        self._ident = {"Buchungstag":"date", "Umsatz in {0}":"value"}
        self.base = 1205.30
        self._readData()

    def _readData(self):

        r = csv.DictReader(self.data_read, delimiter=';')
        dtype = map(lambda x: (self._columns[x][0],self._columns[x][3]),range(len(self._columns)))
        self.data = np.recarray((2), dtype=dtype)
        desiredKeys = map(lambda x:x, self._ident.iterkeys())

        for i, x in enumerate(r):
            for k in desiredKeys:
                if k == "Umsatz in {0}":
                    v = np.float(x[k].replace(",", "."))+self.base           
                else:               
                    v = x[k]
                self.data[self._ident[k]][i] = v 

    def getAllData(self):
        return self.data.copy()   

a = finanz()
b = a.getAllData()
print type(b)
print type(b['value']),type(b['date'])

示例数据

"Buchungstag";"Wertstellung (Valuta)";"Vorgang";"Buchungstext";"Umsatz in {0}";
"02.06.2015";"02.06.2015";"Lastschrift/Belast.";"Auftraggeber: abc";"-3,75";

我现在的问题是为什么键入(b ['date'])类'numpy.core.records.recarray'并键入(b ['value'])类型'numpy.ndarray'??

我的第二个问题是如何以matplotlib可以使用的格式“保存”日期?

第三个也是最后一个问题是如何检查csv文件中的许多行(用于创建空的self.data数组)

THX!

1 个答案:

答案 0 :(得分:0)

在没有额外代码的情况下重复生成数组:

In [230]: dt=np.dtype([('date', 'S15'), ('value', '<f8')])
In [231]: data=np.recarray((2,),dtype=dt)

In [232]: type(data['date'])
Out[232]: numpy.core.records.recarray

In [233]: type(data['value'])
Out[233]: numpy.ndarray

一个字段作为ndarray返回,另一个字段作为recarray返回的事实并不重要。这就是recarray类的设置方式。

现在我们主要使用'结构化数组',例如用

创建
data1=np.empty((2,),dtype=dt)

或填充'0s':

data1=np.zeros((2,),dtype=dt)

# array([('', 0.0), ('', 0.0)], 
  dtype=[('date', 'S15'), ('value', '<f8')])

有了这个,data1['date']['value']都是ndarrayrecarray是旧版本,仍然兼容,但结构化数组的语法和行为更加一致。有很多关于结构化数组的SO问题,其中许多由np.genfromtxt生成,应用于像你这样的csv文件。

我可以结合这个想法,加上我的评论(关于列表追加):

def _readData(self):
    r = csv.DictReader(self.data_read, delimiter=';')
    if self._columns[0][1].endswith('tag'):
        self._columns[0][2] = 'datetime64[D]'
    dtype = map(lambda x: (self._columns[x][0],self._columns[x][3]),range(len(self._columns)))
    desiredKeys = map(lambda x:x, self._ident.iterkeys())
    data = []
    for x in r:
        aline = np.zeros((1,), dtype=dtype)
        for k in desiredKeys:
            if k == "Umsatz in {0}":
                v = np.float(x[k].replace(",", "."))+self.base
            else:
                v = x[k]
                v1 = v.split('.')
                if len(v1)==3:  # convert date to yyyyy-mm-dd format
                     v = '%s-%s-%s'%(v1[2],v1[1],v1[0])
            aline[self._ident[k]] = v
        data.append(aline)
    self.data = np.concatenate(data)

生成b之类的:

array([(datetime.date(2015, 6, 2), 1201.55),
       (datetime.date(2015, 6, 2), 1201.55),
       (datetime.date(2015, 6, 2), 1201.55)], 
       dtype=[('date', '<M8[D]'), ('value', '<f8')])

我相信genfromtxt会将每一行收集为一个元组,并在最后创建数组。结构化数组的文档显示它们可以从

构造
np.array([(item1, item2), (item3, item4),...], dtype=dtype)

我选择为每一行构建一个数组,并在最后连接它们,因为这需要对代码进行更少的更改。

我也更改了该功能,因此它将'tag'列转换为np.datetime64 dtype。关于使用该dtype有许多SO问题。我相信它可以在matplotlib中使用,但我没有相关经验。