使用Pandas vs.CSV reader/writer处理和保存大型CSV fi

2024-10-01 15:34:49 发布

您现在位置:Python中文网/ 问答频道 /正文

我对python和pandas还不太熟悉,但我希望能更好地分析和处理大型数据文件。我现在正在做一个项目,这个项目需要我解析几十个大型CSV CAN文件。这些文件有9个感兴趣的列(1个ID和7个数据字段),大约有100-200万行,并且是用十六进制编码的。在

示例数据如下所示:

   id   Flags   DLC Data0   Data1   Data2   Data3   Data4   Data5   Data6   Data7
cf11505  4      1   ff                          
cf11505  4      1   ff                          
cf11505  4      1   ff                          
cf11a05  4      1   0                           
cf11505  4      1   ff                          
cf11505  4      1   ff                          
cf11505  4      1   ff                          
cf11005  4      8   ff       ff      ff      ff      ff       ff      ff     ff

我需要解码十六进制,然后根据CAN ID从中提取一堆不同的变量

我的一位同事编写了一个脚本来解析这些文件,如下所示(此后称为script#1):

^{pr2}$

它基本上使用CSV读写器为每个CSV逐行生成一个经过处理的CSV文件。对于一个200万行的CSV CAN文件,在我的工作桌面上完全运行大约需要40秒。我知道逐行迭代要比在pandas数据帧上执行矢量化操作慢得多,所以我想我可以做得更好,所以我写了一个如下所示的脚本(script#2):

from timeit import default_timer as timer
import numpy as np
import pandas as pd
import os
import datetime
from tkinter import filedialog
from tkinter import Tk

Tk().withdraw()
filename = filedialog.askopenfile(title="Select .csv log file", filetypes=(("CSV files", "*.csv"), ("all files", "*.*")))

name = os.path.basename(filename.name)
##################################################
df = pd.read_csv(name, skiprows = 7, usecols = ['id', 'Data0', 'Data1', 'Data2', 'Data3', 'Data4', 'Data5', 'Data6', 'Data7'], 
                 dtype = {'id':str, 'Data0':str, 'Data1':str, 'Data2':str, 'Data3':str, 'Data4':str, 'Data5':str, 'Data6':str, 'Data7':str})

log_cols = ['id', 'Data0', 'Data1','Data2', 'Data3', 'Data4', 'Data5', 'Data6', 'Data7']

for col in log_cols: 
    df[col] = df[col].dropna().astype(str).apply(lambda x: int(x, 16))   

df.loc[:, 'Data0':'Data7'] = df.loc[:, 'Data0':'Data7'].fillna(method = 'ffill') #forward fill empty rows
df.loc[:, 'Data0':'Data7'] = df.loc[:, 'Data0':'Data7'].fillna(value = 0) #replace any remaining nans with 0

df['Data0'] = df['Data0'].astype(np.uint8)
df.loc[:, 'Data0':'Data7'] = df.loc[:, 'Data0':'Data7'].astype(np.uint8)

processed_df = pd.DataFrame(np.nan, index= range(0, len(df)), columns= ['var1' 'var2', 'var3', ...])

start_date = datetime.datetime.strptime('7/17/2018 14:12:48','%m/%d/%Y %H:%M:%S')

processed_df ['Time Since Start (s)']  = pd.read_csv(name, skiprows = 7, usecols = ['Time'], dtype = {'Time':np.float32}, engine = 'c')
processed_df['Date'] = pd.to_timedelta(processed_df['Time Since Start (s)'], unit = 's') + start_date
processed_df['id'] = df['id']

processed_df.loc[:, 'var1':'var37'] = processed_df.loc[:, 'var1':'var37'].astype(np.float32)

##################Data Processing###########################
processed_df.loc[processed_df.id == int(0xcf11005), 'var1'] = np.bitwise_or(np.left_shift(df['Data1'], 8), df['Data0'])/10
#a bunch of additional similar vectorized calculations go here to pull useful values

name_string = "Processed_" + name
processed_df.to_csv(name_string) #dump dataframe to CSV

处理部分确实更快,尽管没有我希望的那么快——处理200万行CSV文件大约需要13秒。我可能还可以做更多的工作来优化script#2,但这是另一篇文章的主题。在

无论如何,当我试图将数据帧保存为CSV时,我希望脚本2比脚本1快的希望破灭了。.to\u csv()方法仅用了40秒!我尝试在.to_csv()方法中使用一些参数,包括块大小和压缩,以及减少数据帧的内存占用,但即使进行了这些调整,仍然需要30秒才能保存数据帧,而且一旦考虑到初始处理时间,整个脚本比原始逐行脚本1慢。在

CSV文件的逐行迭代真的是解析这些文件的计算效率最高的方法吗?在


Tags: 文件csvnameimportiddfnploc
2条回答

您是否尝试过设置一个chunksize,即一次要写入的行数,如您所见,here高于100000,它被设置为1。在

另一件要考虑的事情是添加mode='a'(来自默认的w)以进行追加。在

所以我建议使用:

processed_df.to_csv(name_string, mode='a', chunksize=100000)

我会玩chunksize直到它适合你的需要。在

dask库可能值得一看。它实现了pandas数据帧功能的一个子集,但将数据帧存储在磁盘上而不是内存中,并允许您像在内存中一样使用数据帧。我相信它甚至可以将多个文件作为一个数据帧来处理,比如使用多台机器并行处理。在

当我处理一个包含数百万行的6GB CSV时,这个速度更快。在

https://dask.pydata.org/en/latest/

相关问题 更多 >

    热门问题