当在应用中也计算出前一个值时,Pandas 中是否有办法在 dataframe.apply 中使用前一行的值?

2025-01-20 09:07:00
admin
原创
104
摘要:问题描述:我有以下数据框:Index_Date A B C D ================================ 2015-01-31 10 10 Nan 10 2015-02-01 2 3 Nan 22 2015-02-02 ...

问题描述:

我有以下数据框:

Index_Date    A   B     C    D
================================
2015-01-31    10   10   Nan   10
2015-02-01     2    3   Nan   22 
2015-02-02    10   60   Nan  280
2015-02-03    10  100   Nan  250

要求:

Index_Date    A   B    C     D
================================
2015-01-31    10   10    10   10
2015-02-01     2    3    23   22
2015-02-02    10   60   290  280
2015-02-03    10  100  3000  250

Column C2015-01-31通过取得出valueD

然后我需要使用并value乘以并添加。C`2015-01-31valueA2015-02-01B`

我尝试过apply和一个shift使用一个,if else但这给出了一个关键错误。


解决方案 1:

首先,创建派生值:

df.loc[0, 'C'] = df.loc[0, 'D']

然后遍历剩余的行并填充计算的值:

for i in range(1, len(df)):
    df.loc[i, 'C'] = df.loc[i-1, 'C'] * df.loc[i, 'A'] + df.loc[i, 'B']


  Index_Date   A   B    C    D
0 2015-01-31  10  10   10   10
1 2015-02-01   2   3   23   22
2 2015-02-02  10  60  290  280

解决方案 2:

给定一列数字:

lst = []
cols = ['A']
for a in range(100, 105):
    lst.append([a])
df = pd.DataFrame(lst, columns=cols, index=range(5))
df

    A
0   100
1   101
2   102
3   103
4   104

您可以使用以下方式引用上一行shift

df['Change'] = df.A - df.A.shift(1)
df

    A   Change
0   100 NaN
1   101 1.0
2   102 1.0
3   103 1.0
4   104 1.0

fill_value您可以使用参数填充缺失值

df['Change'] = df.A - df.A.shift(1, fill_value=df.A[0]) # fills in the missing value e.g. 100<br>
df

    A   Change
0   100 0.0
1   101 1.0
2   102 1.0
3   103 1.0
4   104 1.0

解决方案 3:

numba

对于不可矢量化的递归计算,numba使用 JIT 编译并与较低级别对象一起工作,通常可以大大提高性能。您只需定义一个常规for循环并使用装饰器@njit或(对于旧版本)@jit(nopython=True)

对于合理大小的数据框,与常规循环相比,这可以使性能提高约 30 倍for

from numba import jit

@jit(nopython=True)
def calculator_nb(a, b, d):
    res = np.empty(d.shape)
    res[0] = d[0]
    for i in range(1, res.shape[0]):
        res[i] = res[i-1] * a[i] + b[i]
    return res

df['C'] = calculator_nb(*df[list('ABD')].values.T)

n = 10**5
df = pd.concat([df]*n, ignore_index=True)

# benchmarking on Python 3.6.0, Pandas 0.19.2, NumPy 1.11.3, Numba 0.30.1
# calculator() is same as calculator_nb() but without @jit decorator
%timeit calculator_nb(*df[list('ABD')].values.T)  # 14.1 ms per loop
%timeit calculator(*df[list('ABD')].values.T)     # 444 ms per loop

解决方案 4:

在 numpy 数组上应用递归函数将比当前答案更快。

df = pd.DataFrame(np.repeat(np.arange(2, 6),3).reshape(4,3), columns=['A', 'B', 'D'])
new = [df.D.values[0]]
for i in range(1, len(df.index)):
    new.append(new[i-1]*df.A.values[i]+df.B.values[i])
df['C'] = new

输出

      A  B  D    C
   0  1  1  1    1
   1  2  2  2    4
   2  3  3  3   15
   3  4  4  4   64
   4  5  5  5  325

解决方案 5:

虽然这个问题已经有一段时间了,但我还是会发布我的答案,希望它能对别人有所帮助。

免责声明:我知道这个解决方案不是标准的,但我认为它效果很好。

import pandas as pd
import numpy as np

data = np.array([[10, 2, 10, 10],
                 [10, 3, 60, 100],
                 [np.nan] * 4,
                 [10, 22, 280, 250]]).T
idx = pd.date_range('20150131', end='20150203')
df = pd.DataFrame(data=data, columns=list('ABCD'), index=idx)
df
               A    B     C    D
 =================================
 2015-01-31    10   10    NaN  10
 2015-02-01    2    3     NaN  22 
 2015-02-02    10   60    NaN  280
 2015-02-03    10   100   NaN  250

def calculate(mul, add):
    global value
    value = value * mul + add
    return value

value = df.loc['2015-01-31', 'D']
df.loc['2015-01-31', 'C'] = value
df.loc['2015-02-01':, 'C'] = df.loc['2015-02-01':].apply(lambda row: calculate(*row[['A', 'B']]), axis=1)
df
               A    B     C     D
 =================================
 2015-01-31    10   10    10    10
 2015-02-01    2    3     23    22 
 2015-02-02    10   60    290   280
 2015-02-03    10   100   3000  250

所以基本上我们使用apply来自 pandas 并借助全局变量来跟踪之前计算的值。


循环的时间比较for

data = np.random.random(size=(1000, 4))
idx = pd.date_range('20150131', end='20171026')
df = pd.DataFrame(data=data, columns=list('ABCD'), index=idx)
df.C = np.nan

df.loc['2015-01-31', 'C'] = df.loc['2015-01-31', 'D']

%%timeit
for i in df.loc['2015-02-01':].index.date:
    df.loc[i, 'C'] = df.loc[(i - pd.DateOffset(days=1)).date(), 'C'] * df.loc[i, 'A'] + df.loc[i, 'B']

每循环 3.2 秒 ± 114 毫秒(7 次运行的平均值 ± 标准差,每次 1 个循环)

data = np.random.random(size=(1000, 4))
idx = pd.date_range('20150131', end='20171026')
df = pd.DataFrame(data=data, columns=list('ABCD'), index=idx)
df.C = np.nan

def calculate(mul, add):
    global value
    value = value * mul + add
    return value

value = df.loc['2015-01-31', 'D']
df.loc['2015-01-31', 'C'] = value

%%timeit
df.loc['2015-02-01':, 'C'] = df.loc['2015-02-01':].apply(lambda row: calculate(*row[['A', 'B']]), axis=1)

每循环 1.82 秒 ± 64.4 毫秒(7 次运行的平均值 ± 标准差,每次 1 个循环)

因此平均速度快 0.57 倍。

解决方案 6:

这是一个老问题,但下面的解决方案(没有 for 循环)可能会有所帮助:

def new_fun(df):
    prev_value = df.iloc[0]["C"]
    def func2(row):
        # non local variable ==> will use pre_value from the new_fun function
        nonlocal prev_value
        new_value =  prev_value * row['A'] + row['B']
        prev_value = row['C']
        return new_value
    # This line might throw a SettingWithCopyWarning warning
    df.iloc[1:]["C"] = df.iloc[1:].apply(func2, axis=1)
    return df

df = new_fun(df)

解决方案 7:

一般来说,避免显式循环的关键是在 rowindex-1==rowindex 上连接(合并)数据框的 2 个实例。

然后,您将拥有一个包含 r 行和 r-1 行的大数据框,您可以从中执行 df.apply() 函数。

然而创建大型数据集的开销可能会抵消并行处理的好处......

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2887  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1752  
  引言PLM(产品生命周期管理)系统在企业项目管理中扮演着至关重要的角色。它涵盖了从产品概念设计到退役的整个生命周期,整合了各种数据和流程。在项目推进过程中,危机难以避免,而PLM系统凭借其强大的功能和特性,能够为项目危机管理提供全面且有效的支持。通过合理运用PLM系统,企业可以提前预防危机、在危机发生时迅速做出响应并采...
plm系统功能介绍   14  
  PLM(产品生命周期管理)系统在企业日常运营中扮演着至关重要的角色,它涵盖了产品从概念设计到退役的整个生命周期,涉及多个部门和环节。有效的系统维护能够确保PLM系统稳定运行,提升企业的生产效率、产品质量以及创新能力。以下将详细阐述PLM系统维护在日常运营中的6个关键环节。系统监控与性能优化系统监控是保障PLM系统正常运...
PLM项目管理软件   14  
  引言产品生命周期管理(PLM)系统在现代企业的运营中扮演着至关重要的角色。它不仅仅是一个管理产品数据的工具,更是推动企业持续改进的强大引擎。在追求卓越质量的道路上,PLM系统与质量工具的有效结合能够释放巨大的能量。2025年,随着市场竞争的日益激烈和客户需求的不断变化,企业需要更加深入地挖掘PLM系统的潜力,通过实践先...
免费plm管理软件   16  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用