我希望得到一些关于我在大型(约 1000 万行)pandas 数据帧上的迭代过程的最佳方法的建议。我正在使用Python 3.7。数据框的结构如下:
start_time flag
0 2019-12-01 15:31:42 True
1 2019-12-01 15:32:37 False
2 2019-12-01 15:47:58 False
3 2019-12-02 09:19:13 True
4 2019-12-02 09:21:12 False
5 2019-12-02 09:24:04 False
6 2019-12-02 11:26:31 False
7 2019-12-02 12:10:56 False
8 2019-12-02 12:25:13 False
9 2019-12-02 13:09:25 False
我想做的是:
每次该标志为 true 时,就将新列 start_day
和 start_hour
指定为 start_time
列中的日期和小时值。每次标志为 false 时,将 start_day
和 start_hour
分配给前一个索引中的值。
所以想要的结果是:
start_datetime flag start_day start_hour
0 2019-12-01 15:31:42 True 1 15
1 2019-12-01 15:32:37 False 1 15
2 2019-12-01 15:47:58 False 1 15
3 2019-12-02 09:19:13 True 2 9
4 2019-12-02 09:21:12 False 2 9
5 2019-12-02 09:24:04 False 2 9
6 2019-12-02 11:26:31 False 2 9
7 2019-12-02 12:10:56 False 2 9
8 2019-12-02 12:25:13 False 2 9
9 2019-12-02 13:09:25 False 2 9
有关更多信息,flag
列的 False 大约为 90%,但 True 值之间的差距差异很大。
这是我迄今为止尝试过的:
def startBuilder(df):
df.loc[df['flag'], 'start_day'] = 1
df.loc[~df['flag'], 'start_day'] = 0
df['start_day'] = df['start_day'] * pd.DatetimeIndex(df['start_datetime']).day
df.loc[df['flag'], 'start_hour'] = 1
df.loc[~df['flag'], 'start_hour'] = 0
df['start_hour'] = df['start_hour'] * pd.DatetimeIndex(df['start_datetime']).hour
for i, data in df.iterrows():
if not data['flag']:
df.at[i, 'start_year'] = df.at[i - 1, 'start_year']
df.at[i, 'start_month'] = df.at[i - 1, 'start_month']
df.at[i, 'start_day'] = df.at[i - 1, 'start_day']
df.at[i, 'start_hour'] = df.at[i - 1, 'start_hour']
return df
我可以将此数据流式传输/分块到此函数中吗?如果是这样,最好的方法是什么?
是否可以优化此函数以利用 flag
为 90% false 的事实?
我尝试了以下方法,但速度非常慢(比上面的慢大约 9 倍):
def startBuilder2(df):
df.loc[df['flag'], 'start_day'] = 1
df.loc[~df['flag'], 'start_day'] = 0
df['start_day'] = df['start_day'] * pd.DatetimeIndex(df['start_datetime']).day
df.loc[df['flag'], 'start_hour'] = 1
df.loc[~df['flag'], 'start_hour'] = 0
df['start_hour'] = df['start_hour'] * pd.DatetimeIndex(df['start_datetime']).hour
idx1 = df[df['flag']].index
idx_pair = zip(idx1[:-1], idx1[1:])
for pair in idx_pair:
df.at[(~df['flag']) & (df['flag'].index.to_series().between(pair[0], pair[1])), 'start_day'] = df.at[pair[0], 'start_day']
df.at[(~df['flag']) & (df['flag'].index.to_series().between(pair[0], pair[1])), 'start_hour'] = df.at[pair[0], 'start_hour']
return df
对这么长的帖子表示歉意,只是想提供尽可能多的背景信息。提前致谢。
最佳答案
你可能不需要分块。看看这是否适合您。
df['start_day'] = np.nan
df['start_hour'] = np.nan
mask = df['flag'].eq(True)
df.loc[mask, 'start_day'] = df.loc[mask, 'start_time'].dt.day
df.loc[mask, 'start_hour'] = df.loc[mask, 'start_time'].dt.hour
df.loc[:, ['start_day', 'start_hour']] = df.loc[:, ['start_day', 'start_hour']].ffill()
关于python - 如何通过分块或流式传输来优化大型(不是巨大)Pandas 迭代过程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59606972/