在Pandas数据库中加速交叉引用过滤

4

我正在处理一个非常大的捐款数据库,其中包含与捐赠ID、通道ID、金额相关的列,例如:

  TRANSACTION_ID BACK_REFERENCE_TRAN_ID_NUMBER  CONTRIBUTION_AMOUNT
0    VR0P4H2SEZ1                             0                  100
1    VR0P4H3X770                             0                 2700
2    VR0P4GY6QV1                             0                  500
3    VR0P4H3X720                             0                 1700
4    VR0P4GYHHA0                  VR0P4GYHHA0E                  200

我需要做的是识别所有TRANSACTION_ID对应任何BACK_REFERENCE_TRAN_ID_NUMBER的行。我的现有代码虽然有点笨拙,但是如下所示:
is_from_conduit = df[df.BACK_REFERENCE_TRAN_ID_NUMBER != "0"].BACK_REFERENCE_TRAN_ID_NUMBER.tolist()
df['CONDUIT_FOR_OTHER_DONATION'] = 0
for row in df.index:
    if df['TRANSACTION_ID'][row] in is_from_conduit:
        df['CONDUIT_FOR_OTHER_DONATION'][row] = 1
    else:
        df['CONDUIT_FOR_OTHER_DONATION'][row] = 0

然而,在非常大的数据集中,如果有大量的通道捐赠,这将需要很长时间。我知道一定有更简单的方法,但显然我无法想出如何表达来找出可能的解决方案。


1
df.iloc[4, 1] 后面多了一个 'E' 是有原因的吗? - Alex
我稍微编辑了一下,以便更容易地复制/粘贴。这不应该改变你写的内容。然而,我不明白你的意思。你能展示一下你期望的输出吗?在这里,你的列CONDUIT_FOR_OTHER_DONATION只有0 - jrjc
  1. VR0P4GYHHA0 <> VR0P4GYHHA0E
- Merlin
2个回答

5
你可以使用 Series.isin。它是一种矢量化操作,用于检查系列的每个元素是否在提供的可迭代对象中。
df['CONDUIT_FOR_OTHER_DONATION'] = df['TRANSACTION_ID'].isin(df['BACK_REFERENCE_TRAN_ID_NUMBER'].unique())

正如@root所提到的,如果您更喜欢0/1(就像您的示例一样),而不是True/False,您可以将其转换为int

df['CONDUIT_FOR_OTHER_DONATION'] = df['TRANSACTION_ID'].isin(df['BACK_REFERENCE_TRAN_ID_NUMBER'].unique()).astype(int)

1
我认为你应该添加一个 .astype(int),因为 isin 返回布尔值,而示例代码似乎给出了 0/1 值。 - root
返回T/F或1/0对长期没有影响,但无论哪种方式都完美地解决了问题。谢谢! - whateveryousayiam

2
这是一种基于 NumPy 的方法,使用 np.in1d -
vals = np.in1d(df.TRANSACTION_ID,df.BACK_REFERENCE_TRAN_ID_NUMBER).astype(int)
df['CONDUIT_FOR_OTHER_DONATION'] = vals

np.in1D()似乎只返回成员关系--你如何获取位置或索引值呢? - Merlin
@Merlin 我不确定我们需要成员身份还是职位,因为它一次性获取整个输出列,我们只是在现有数据框中分配一个新列并将值 vals 放入其中。或者我错过了什么? - Divakar
该函数提供了成员资格。我想知道是否可以获取位置或索引。文档中的 [0,2,0] 是成员资格,但元素的索引是什么?第二个“0”的索引为5。我该如何获取它。 - Merlin
@Merlin 啊!假设我理解了你的问题,使用 np.where(np.in1d(..))?哦,如果你是想对应哪些元素来自哪里,我们可以使用 np.searchsorted。回到问题上,我认为 OP 是想要在输出列中得到 01,就像 OP 发布的代码建议的那样。 - Divakar
刚刚检查了np.searchsorted会给出元素在已排序的“列表”中的位置,而不是原始“列表”的索引。 - Merlin
@Merlin 我们需要使用可选参数:sorter=first_input.argsort() - Divakar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接