我有一个处理DataFrame的函数,主要用于将数据处理到存储桶中,使用会在特定列中创建功能的二进制矩阵pd.get_dummies(df[col])。
pd.get_dummies(df[col])
为了避免立即使用此函数处理所有数据(该数据将耗尽内存并导致iPython崩溃),我使用以下方法将大型DataFrame分为多个块:
chunks = (len(df) / 10000) + 1 df_list = np.array_split(df, chunks)
pd.get_dummies(df)会自动创建一个基于内容的新栏目df[col]和这些都有可能为每个不同df在df_list。
pd.get_dummies(df)
df[col]
加工后,我串接DataFrames回到一起使用:
for i, df_chunk in enumerate(df_list): print "chunk", i [x, y] = preprocess_data(df_chunk) super_x = pd.concat([super_x, x], axis=0) super_y = pd.concat([super_y, y], axis=0) print datetime.datetime.utcnow()
第一块的处理时间是完全可以接受的,但是,每个块会增加!这与无关,preprocess_data(df_chunk)因为没有理由增加它。通话是否会增加时间pd.concat()?
preprocess_data(df_chunk)
pd.concat()
请查看以下日志:
chunks 6 chunk 0 2016-04-08 00:22:17.728849 chunk 1 2016-04-08 00:22:42.387693 chunk 2 2016-04-08 00:23:43.124381 chunk 3 2016-04-08 00:25:30.249369 chunk 4 2016-04-08 00:28:11.922305 chunk 5 2016-04-08 00:32:00.357365
有没有解决方法可以加快速度?我有2900个区块需要处理,因此我们将不胜感激!
欢迎使用Python中的其他建议!
不要调用DataFrame.append或pd.concat一个for循环中。这导致二次复制。
DataFrame.append
pd.concat一个for
pd.concat返回一个新的DataFrame。必须为新的DataFrame分配空间,并且必须将旧DataFrame中的数据复制到新的DataFrame中。考虑以下行中所需的复制数量for-loop(假设每个副本的x大小为1):
pd.concat
DataFrame
for-loop
super_x = pd.concat([super_x, x], axis=0) | iteration | size of old super_x | size of x | copying required | | 0 | 0 | 1 | 1 | | 1 | 1 | 1 | 2 | | 2 | 2 | 1 | 3 | | ... | | | | | N-1 | N-1 | 1 | N |
1 + 2 + 3 + ... + N = N(N+1)/2。因此,O(N**2)需要一些副本才能完成循环。
1 + 2 + 3 + ... + N = N(N+1)/2
O(N**2)
现在考虑
super_x = [] for i, df_chunk in enumerate(df_list): [x, y] = preprocess_data(df_chunk) super_x.append(x) super_x = pd.concat(super_x, axis=0)
追加到列表是一项O(1)操作,不需要复制。pd.concat循环完成后,现在只有一个调用。pd.concat由于super_x包含N 大小为1的DataFrame,因此对N的调用 需要进行N个拷贝。因此,以这种方式构造时,super_x需要O(N) 拷贝。