使用Python Dataframe将行与下一行进行比较并从结果中创建一个新列?

Posted

技术标签:

【中文标题】使用Python Dataframe将行与下一行进行比较并从结果中创建一个新列?【英文标题】:Compare row with next row and create a new column from results, using Python Dataframe? 【发布时间】:2020-10-27 21:26:23 【问题描述】:

我想比较两列中的两个连续行,如果它们的值相同,则根据第三列值之间的差异创建一个新列。请参阅下面的输入和预期输出:

输入:

df = pd.Dataframe('Account Number': [123,123,123,456,456,456],  'Value':['ABC', 'ABC', 'ABC', 'DEF', 'DEF', 'DEF'],'Positions':[10,10,20,20,20,15])

预期输出:

df = pd.Dataframe('Account Number': [123,123,123,456,456,456],'Value':['ABC', 'ABC', 'ABC', 'DEF', 'DEF', 'DEF'],'Positions':[10,10,20,20,20,15], 'new_col': [0,0,10,0,0,-5])

在excel中,公式很简单:

IF(AND(B2=B1,C2=C1), D2-D1, 0)

其中:B = 帐号,C = 价值,D = new_col

到目前为止,我已经尝试了两次尝试 - (1) 使用 iloc(这会产生 IndexError: Single positional indexer is out of bounds")和 (2) 使用 rolling(n) - 但我不能甚至编译。请参阅下面我在 (1) 处的尝试,任何帮助都会很棒。谢谢!

a = 0
if a != len(df):
    for a in range(len(df)):
        df['new_col'] = np.where((df["Account Number"].iloc[a+1] == df["Account Number"].iloc[a]) and (df["Value"].iloc[a+1] == df["Value"].iloc[a]), df["Positions"].iloc[a+1] df["Positions"].iloc[a], 0)
        a+= 1

【问题讨论】:

【参考方案1】:

您应该使用一种称为.diff() 的简单且性能更高的pandas 方法而不是循环:

df['new_col'] = df.groupby('Account Number')['Positions'].diff().fillna(0).astype(int)

完整代码:

df = pd.DataFrame('Account Number': [123,123,123,456,456,456],  'Value':['ABC', 'ABC', 'ABC', 'DEF', 'DEF', 'DEF'],'Positions':[10,10,20,20,20,15])
df['new_col'] = df.groupby('Account Number')['Positions'].diff().fillna(0).astype(int)
df
Out[1]: 
   Account Number Value  Positions  new_col
0             123   ABC         10        0
1             123   ABC         10        0
2             123   ABC         20       10
3             456   DEF         20        0
4             456   DEF         20        0
5             456   DEF         15       -5

【讨论】:

谢谢大卫 - 但是,这个解决方案不是我想要的,因为它不会检查 (1) 'Account Number' 的当前行和下一行是否相同并且 (2 ) 'Value' 的当前行和下一行是相同的。但是,您提出了一个很好的观点,即使用 diff 方法来进行逐行比较,而不是循环。你知道该怎么做吗? @samoa_like_Moana 简单!只是 groupby 帐号。查看更新的答案! 是的!实际上 groupby 需要同时具有“帐号”和“价值”,然后它就是解决方案。谢谢大卫!!【参考方案2】:

对于范围内的(len(df)-1):

注意 -1。 没有它 - 是的,你会遇到索引错误

【讨论】:

【参考方案3】:

应该避免循环遍历 pandas 结构,但我不知道如何在没有循环或修改数据结构的情况下为您提供帮助

new_col=[0]
for a in range(len(df)-1):
    if (df["Account Number"].iloc[a+1] == df["Account Number"].iloc[a]) and (df["Value"].iloc[a+1] == df["Value"].iloc[a]):
        new_col.append(df["Positions"].iloc[a+1] - df["Positions"].iloc[a])
    else:
        new_col.append(0)

df["new_col"]=new_col
print(df)

给出以下输出

   Account Number Value  Positions  new_col
0             123   ABC         10        0
1             123   ABC         10        0
2             123   ABC         20       10
3             456   DEF         20        0
4             456   DEF         20        0
5             456   DEF         15       -5

【讨论】:

我看到已经发布了一个利用 pandas 功能的答案。如果您不需要您提到的条件检查,您应该选择 David Erickson diff() 解决方案。如果你不这样做,找到一种避免循环的方法仍然是件好事。 谢谢 TriGiamp - 这个解决方案效果很好。不幸的是,我确实需要条件检查。

以上是关于使用Python Dataframe将行与下一行进行比较并从结果中创建一个新列?的主要内容,如果未能解决你的问题,请参考以下文章

用于将当前行与下一行进行比较并根据条件打印其中一行的 awk 解决方案

根据第一列中的字母数将行与上一行连接起来

将行分组到一个新的 Pandas DataFrame 中,每组一行

使用 MySQL 数据填充 div,将行与编号 ID 匹配

DataFrame:将行转换为 dict python?

Bootstrap 4将行与容器底部对齐