600k行csv文件使用python进行解析/格式化非常慢

时间:2016-01-04 10:56:50

标签: python parsing csv pandas

我的第一个问题就在这里,因为我几天前开始使用python。 我对VBA和Matlab有很好的经验,但是我目前正在尝试使用python作为练习,并且因为它背后有更大的(是吗?)量子社区。

我在搜索之前搜索了很多,我甚至使用了一些代码片段,这些代码片段是我在做我的时候从其他用户那里找到的(感谢大家)。

问题是,我正在读取大约630k行(15mb)的刻度数据csv,因此我可以提取其第三列(最后一个刻度/交易)并为它们创建一个结构(matlab术语) ,DataFrame格式中所有刻度的列向量,这样我就可以计算它们的pct_change(pandas)。

我让它隔夜运行大约6个小时,它仍然是@ ~150k / 630k 我确信我做的事情非常低效。

我目前正在使用spyder,在Windows 7,4gb ram,i3核心上运行,并没有真正负载过重。

以下是代码:

- resourceLoader:didCancelLoadingRequest:

csv格式:

"""""""""""""""""""""""""""""""""""""""
created on Sun Jan 03 12:59:25 2016
@author: eduardo
"""""""""""""""""""""""""""""""""""""""

import pandas as pd
import csv as csv
from datetime import datetime
startTime = datetime.now()

path = "C:\Users\eduardo\.xy\startups"
data = "C:\Users\eduardo\.xy\startups\INDV14.CSV"

delimeters = [' ', ';'] # matrix [1,2]

unique = '[]'  # empty struct ?
close = [] # empty matrix for later use

with open(data) as data: # data = csv
    for row in data: # counter to loop for inside csv
        for cols in data: # another counter for separating columns now
            for d in delimeters:cols = unique.join(cols.split(d))
            # last for loop does not need ":" ? 
            # from d to d+n, step 1
            # splits columns using "d" separators defined above
            # joins them after splitting, by a "[]" separator "space" ?
            row = cols.split(unique) # row = for each row splitted
            close.append(row[2]) # call third column of each (row) 
            # fill the empty matrix created above (close) row by row
            # with it up with a column vector of my 3rd col of the CSV
            ticks = map(int, close) # coverts strings to integers
            # format the column vector above to pandas DataFrame format
            deals = pd.DataFrame(ticks)
            # call pct_change function of pandas 
            daily_returns = deals.pct_change(periods=1)
            print(daily_returns)
    data.close() # closes csv file 

    # creates a new file ("W"rite), returns.csv
    dataCSV = open('returns.csv', 'w') 
    for line in daily_returns: # de for each line in the daily returns struct
        dataCSV.write(line) # writes them in the new csv file 
    dataCSV.close() # closes new file

    datetime.now() - startTime # time counter 

3 个答案:

答案 0 :(得分:1)

我认为如果你告诉pandas解析你的日期并通过分隔符,这将会奏效:

In [7]:
import pandas as pd
import io
t="""20140801 105159;57085;5
20140801 105206;57085;5"""

df = pd.read_csv(io.StringIO(t), sep=';', header=None, parse_dates=[0])
df

Out[7]:
                    0      1  2
0 2014-08-01 10:51:59  57085  5
1 2014-08-01 10:52:06  57085  5

所以在你的情况下,这应该有效:

df = pd.read_csv(data, header=None, parse_dates=[0], sep=';')

然后你可以把它写成csv:

df.to_csv('returns.csv') 

你可以看到pandas正确地嗅探了dtypes:

In [8]:
df.info()

<class 'pandas.core.frame.DataFrame'>
Int64Index: 2 entries, 0 to 1
Data columns (total 3 columns):
0    2 non-null datetime64[ns]
1    2 non-null int64
2    2 non-null int64
dtypes: datetime64[ns](1), int64(2)
memory usage: 64.0 bytes

答案 1 :(得分:0)

如果你想只拉第三列,你可以做得更简单,使用csv lib并在分号上拆分并使用第二个元素,这相当于拆分代码中使用的第三列:

import csv
from operator import itemgetter
with open(data) as data: # data = csv
    for ith in map(itemgetter(1), csv.reader(data, delimiter=";")):
        print(ith)

虽然会输出:

57085
57085

在你自己的代码中,你在循环中创建DF,这样你就不会在最后一次调用时存储任何数据条,所以即使它完成了你也基本上没有数据要写。如果你真的想要在分号上进行Dataframe拆分并提取第二列df = pd.read_csv(data,sep=";",usecols=[1], header=None),那么会给你:

   1
0  57085
1  57085

同样unique = '[]' # empty struct ?也会创建一个字符串,unique.join(cols.split(d))将所有数据连接在一起,用“[]”分隔,然后你row = cols.split(unique),这正是你{{1}之前所拥有的}}。

另外,如果你想要一个只有第二列的数组,你可以使用numpy.genfromtxt

cols.split(d)

哪会给你:

import numpy as np

arr = np.genfromtxt(data, usecols=[1], delimiter=";")

print(arr)

或者,如果您想要更改百分比:

[57085.  57085.]

如果您想使用完整的Dataframe来合并日期以用于获取每日更改百分比等等:

pct_chnge = np.diff(arr) / arr[:-1]

答案 2 :(得分:0)

感谢所有回复的人:

这是在你的帮助之后它是如何结束的:

`# -*- coding: utf-8 -*-
"""""""""""""""""""""""""""
Created on Mon Jan 04 09:21:10 2016
@author: eduardo
"""""""""""""""""""""""""""

from datetime import datetime
startTime = datetime.now()

import pandas as pd
import csv 
from operator import itemgetter

data = "C:\Users\eduardo\.xy\startups\INDV14.CSV" # address
ticks = [] # calling empty matrix

with open(data) as data: # data = original csv
    # for i(n) in first column after ";" in the open csv, "str" to "int"  
    for ith in map(int,map(itemgetter(1), csv.reader(data, delimiter=";"))):
        # call empy matrix shell above and fill it row by row with "int"s
        ticks.append(ith)
        data.close() # close csv file so it doesnt get stuck

# format matrix above ("ticks) to pandas DF format
prcnt_chng_df = pd.DataFrame(ticks)
# use pandas percent change (period=1) function for above DF with padding
prcnt_chng = prcnt_chng_df.pct_change(periods=1, fill_method='pad')
# print above structure of pct changes starting on the 2nd row
# no indexing since i dont need them and it would make the file bigger
print((prcnt_chng)[1:].to_csv('indv14_rets.csv', index=False))

timer = datetime.now() - startTime
print(timer) # counter`

我设法得到了我想要的东西,所以我现在可以将这个新的csv文件调用到其他一些脚本中,以便计算一个月内发生的未来合同的滴答作用的滴答间隔密度。

所有这些都是在0:00:02.996000

中完成的

最好的问候