我有以下代码片段,它将CSV读入数据帧,并以与Redis协议兼容的方式将键值对写入文件,即SET key1 value1
。代码是零碎的,我尝试过使用多处理,尽管我不确定它的性能(收益)。在
CSV有大约600万行,可以很快(不到2分钟)读入数据帧。输出文件有1200万行(输入文件每行2行)。这大约需要50分钟才能完成。我的代码的任何部分可以被优化/更改以使它运行得更快吗?文件完成后,将其加载到Redis所需时间不到90秒。真正的瓶颈在于对文件的写入。我会有几个这样的文件写和花费50-60分钟每个文件真的不理想。这个特定的数据集有600万行和10列,大部分由字符串和一些浮动列组成。Redis键是字符串,浮点值是键值对中的Redis值。其他数据集的大小也将类似,如果不是更大的话(包括行和列)。在
我想把我生成的所有字符串加载到一个数据帧中,然后使用to_csv()函数将其转储到一个文件中,但我不确定它的性能如何。在
filepath = '/path/to/file.csv'
def df_to_file:
df = pd.read_csv(filepath)
f = open('output_file', 'w')
for i in range(len(df.index)):
if df['col1'].iloc[i] != '':
key1 = str(df['col1'].iloc[i])+str(df['col4'].iloc[i])+str(df['col5'].iloc[i])+...+str(df['col_n'].iloc[i])
val1 = df['col_n+1'].iloc[i]
key1a = str(df['col1'].iloc[i])+str(df['col4'].iloc[i])+str(df['col5'].iloc[i])+...+str(df['col_n'].iloc[i])
val1a = df['col_n+2'].iloc[i]
print('SET {0} {1}\nSET {0} {1}'.format(key1, val1, key1a, val1a), file = f)
if df['col2'].iloc[i] != '':
key1 = str(df['col2'].iloc[i])+str(df['col4'].iloc[i])+str(df['col5'].iloc[i])+...+str(df['col_n'].iloc[i])
val1 = df['col_n+1'].iloc[i]
key1a = str(df['col2'].iloc[i])+str(df['col4'].iloc[i])+str(df['col5'].iloc[i])+...+str(df['col_n'].iloc[i])
val1a = df['col_n+2'].iloc[i]
print('SET {0} {1}\nSET {0} {1}'.format(key1, val1, key1a, val1a), file = f)
if df['col3'].iloc[i] != '':
key1 = str(df['col3'].iloc[i])+str(df['col4'].iloc[i])+str(df['col5'].iloc[i])+...+str(df['col_n'].iloc[i])
val1 = df['col_n+1'].iloc[i]
key1a = str(df['col3'].iloc[i])+str(df['col4'].iloc[i])+str(df['col5'].iloc[i])+...+str(df['col_n'].iloc[i])
val1a = df['col_n+2'].iloc[i]
print('SET {0} {1}\nSET {0} {1}'.format(key1, val1, key1a, val1a), file = f)
f.close()
p = Process(target = df_to_file)
p.start()
p.join()
使用像
df['col1'].loc[...]
这样的结构来循环单个行是很慢的,基于iloc
和loc
的选择器用于在整个数据帧中选择,并执行大量与索引对齐相关的工作,如果对每一行执行这些操作,则会有很高的开销。相反,简单地使用df.itertuples()
来迭代行将大大加快。在这也许是你能做的最低限度的优化。如果你更详细地描述你正在做什么,也许可以找到一个矢量化的解决方案。在
另外,不要将上述内容与
multiprocessing
一起使用。在而且,正如所写,
'SET {0} {1}\nSET {0} {1}'.format(key1, val1, key1a, val1a)
将始终是相同的。如果这些参数没有改变,那么只需在循环外执行一次字符串连接,然后在循环中重用整个字符串。在编辑:似乎你不能这么做,但鉴于:
那么只要
key1 = ''.join(row.col1, row.col4, row.col5, ...)
不要使用str
和+
运算符,这是非常低效的,因为你暗示那些列已经是字符串了。如果您必须对所有这些列调用str
,请使用map(str, ...)
最后,如果您真的需要压缩性能,请注意}(注意,},i、 索引)`这应该更快(而且这会产生不同的效果,因为每次迭代都会对元组进行几十次索引,并进行数百万次迭代)。在
row
将是namedtuple
对象,它是元组,并且您可以使用基于整数的索引而不是基于属性的标签访问,即row[1]
而不是{row[0]
将是{相关问题 更多 >
编程相关推荐