python - 如何通过分块或流式传输来优化大型(不是巨大)Pandas 迭代过程?

标签 python pandas

我希望得到一些关于我在大型(约 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_daystart_hour 指定为 start_time 列中的日期和小时值。每次标志为 false 时,将 start_daystart_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/

相关文章:

python - 有什么方法可以替换 pandas pd.merge 吗?

python - 关于索引的 bin 成员资格添加两个系列的 Pandonic 方法

python - 错误 : unpack_from requires a buffer

python - 应用过滤器后引用 django-templates 中的键/值

python - PyMQI for windows 构建和安装

python - 填补多个用户缺失的时间段

python - 如何在多线回归中对解释变量求平方

python - 如何使用索引替换列值的前两个字母

围绕枚举的 Pythonic 方式

Python dash Div整页背景图片