【问题标题】:pandas loop on elements熊猫循环元素
【发布时间】:2025-11-24 13:10:02
【问题描述】:

我想计算数据帧中的增量时间(在某些条件下),所以我写了一个循环:

for i in range(1,len(df.index)):
    if df.type[i] == df.type[i-1]:
        df.delta[i]=df.time[i]-df.time[i-1]
    else:
        df.delta[i]= ''

但它似乎不是很优化,因为它很长而且我得到一个SettingWithCopyWarning(我不明白)。进行此类计算的最佳方法是什么?

【问题讨论】:

    标签: python performance pandas loops dataframe


    【解决方案1】:

    我会为此使用 .shift() 。它创建一个新列,其中的值移动了 1。 因此,如果我们没有条件,您只需要df["time"] - df["time"].shift(),但如果您想添加条件,where 会有所帮助。所以这是一个单行解决方案

    (df["time"] - df["time"].shift()).where(df["type"] == df["type"].shift(), "")
    

    或者按照其他答案中的建议,您可以使用 diff

    df["time"].diff().where(df["type"] == df["type"].shift(), "")
    

    【讨论】:

      【解决方案2】:

      您应该使用矢量化方法。例如,您可以将numpy.wherepd.Series.shiftpd.Series.diff 一起使用:

      df['C_id'] = np.where(df['type'] == df['type'].shift(), df['time'].diff(), np.nan)
      

      注意,我强烈建议您不要使用空字符串 '' 作为替代值,因为这将强制您的系列使用 object dtype 而不是 float

      【讨论】:

        【解决方案3】:

        我的方法是使用 pandas.apply()

        type_prev = ''
        time_prev = 0
        
        def lambda_func(row):
            global type_prev
            global time_prev
            if row['type'] == time_prev:
                time_diff = row['time'] - time_prev
            else:
                time_diff = ''
            time_prev = row['time']
            type_prev = row['type']
            return time_diff
        
        df['delta'] = df.apply(lambda_func)
        

        【讨论】:

        • 好像不行,试试这个:df = pd.DataFrame(np.random.randn(10, 4), columns=list('ABCD')) df.A[ 0:2] = 1 df.A[2:5] = 4 df.A[5:9] = 3 type_prev = '' time_prev = 0 def lambda_func(row): global type_prev global time_prev if row['A'] == time_prev: time_diff = row['B'] - time_prev else: time_diff = '' time_prev = row['B'] type_prev = row['A'] return time_diff df['C'] = df.apply(lambda_func )