Pandas:在组复杂问题中使用条件迭代和插入列

Posted

技术标签:

【中文标题】Pandas:在组复杂问题中使用条件迭代和插入列【英文标题】:Pandas: Iterate and insert column with conditions within groups complex question 【发布时间】:2020-10-23 18:54:22 【问题描述】:

我有一个非常复杂的问题,即如何为每个组添加一个包含条件的新列。这是示例数据框,

df = pd.DataFrame(
    'id': ['AA', 'AA', 'AA', 'AA', 'BB', 'BB', 'BB', 'BB', 'BB',
           'CC', 'CC', 'CC', 'CC', 'CC', 'CC', 'CC'],
    'From_num': [80, 68, 751, 'Issued', 32, 68, 126, 'Issued', 'Missed', 105, 68, 114, 76, 68, 99, 'Missed'],
    'To_num':[99, 80, 68, 751, 105, 32, 68, 126, 49, 324, 105, 68, 114, 76, 68, 99],
)
    id From_num  To_num
0   AA       80      99
1   AA       68      80
2   AA      751      68
3   AA   Issued     751
4   BB       32     105
5   BB       68      32
6   BB      126      68
7   BB   Issued     126
8   BB   Missed      49
9   CC      105     324
10  CC       68     105
11  CC      114      68
12  CC       76     114
13  CC       68      76
14  CC       99      68
15  CC   Missed      99

我有一个 'flag' 编号 68。​​在每个组中,对于 'From_num' 列中等于或高于此标志号的任何行将在新列中标记为“Forward”,任何行等于或低于标志号“To_num”列将在同一列中标记为“Back”。然而,最困难的情况是:如果这个标志号在每一列中出现多次,'From_num' 和 'To_num' 之间的行将在新列中标记为“Forward&Back”,请参见下面的 df 和预期结果。

Expected result
    id From_num  To_num     Direction
0   AA       80      99       Forward
1   AA       68      80       Forward
2   AA      751      68          Back
3   AA   Issued     751          Back
4   BB       32     105       Forward
5   BB       68      32       Forward
6   BB      126      68          Back
7   BB   Issued     126          Back
8   BB   Missed      49          Back
9   CC      105     324       Forward
10  CC       68     105       Forward 
11  CC      114      68  Forward&Back # From line 11 to 13, flag # 68 appears more than once
12  CC       76     114  Forward&Back # so the line 11, 12 and 13 labelled "Forward&Back"
13  CC       68      76  Forward&Back 
14  CC       99      68          Back 
15  CC   Missed      99          Back

我尝试编写了许多循环,但它们都失败了,无法获得预期的结果。因此,如果有人有想法,请提供帮助。希望问题很清楚。非常感谢!

【问题讨论】:

【参考方案1】:

我已经完成了没有“真正的循环”。

    保留行号 (reset_index()) 构造一个新的数据框,它是包含标志 (68) 的记录 “前进”和“后退”的简单逻辑基于第一次看到 68 之前或之后的行 “向前和向后”发生在有多次目击以及在第 2 次和第 (n-1) 次目击之间
def direction(r):
    flagrow = df2[(df2["id"]==r["id"]) ]["index"].values
    if r["index"] <= flagrow[0]: val = "Forward"
    elif r["index"] > flagrow[0]: val = "Back"
    if len(flagrow)>2 and r["index"] >= flagrow[1] and r["index"]<flagrow[-1]: val = "Forward&Back"

    return val

df = pd.DataFrame(
    'id': ['AA', 'AA', 'AA', 'AA', 'BB', 'BB', 'BB', 'BB', 'BB',
           'CC', 'CC', 'CC', 'CC', 'CC', 'CC', 'CC'],
    'From_num': [80, 68, 751, 'Issued', 32, 68, 126, 'Issued', 'Missed', 105, 68, 114, 76, 68, 99, 'Missed'],
    'To_num':[99, 80, 68, 751, 105, 32, 68, 126, 49, 324, 105, 68, 114, 76, 68, 99],
)
df = df.reset_index()
df2 = df[(df.From_num==68) | (df.To_num==68)].copy()
df["Direction"] = df.apply(lambda r: direction(r), axis=1)
df

【讨论】:

非常感谢@Rob Raymond,我尝试了您的回答,效果很好。一百万谢谢!让我再试几次,然后回复你。 不客气 - 数据的关键是将其视为集合并进行基于集合的处理。过程编程概念用于控制逻辑。 Codd 早在 1970 年就做到了 :-)

以上是关于Pandas:在组复杂问题中使用条件迭代和插入列的主要内容,如果未能解决你的问题,请参考以下文章

Pandas 在组和支点报告中排名前 n

在组内使用 pandas.shift()

迭代 Pandas DataFrame 并插入行的最快方法

Pandas:使用大文件的行和列的条件优化迭代

如何使用 Pandas groupby 在组上添加顺序计数器列

Pandas 变量在组内移动