两个数据帧的Pandas布尔索引

2024-06-17 08:00:03 发布

您现在位置:Python中文网/ 问答频道 /正文

我有两个pandas数据帧:

df1
'A' 'B'
 0   0
 0   2
 1   1
 1   1
 1   3

df2
'ID' 'value'
 0   62
 1   70
 2   76
 3   4674
 4   3746

我想将df.value作为一个新列D分配给df1,但是当df.A == 0时。 df1.B和{}应该是标识符。在

输出示例:

^{pr2}$

我尝试了以下方法:

df1['D'][ df1.A == 0 ] = df2['value'][df2.ID == df1.B]

但是,由于df2和df1的长度不一样,我得到了一个ValueError。在

ValueError: Series lengths must match to compare

这完全是由于最后一部分中的布尔索引:[df2.ID == df1.B]

有人知道如何在不需要迭代数据帧的情况下解决问题吗?在

多谢了!在

=============

Edit回复@EdChum:它完美地处理了示例数据,但我的实际数据有问题。df1是一个巨大的数据集。df2如下所示:

df2
    ID  value
0   1   1.00000
1   2   1.00000
2   3   1.00000
3   4   1.00000
4   5   1.00000
5   6   1.00000
6   7   1.00000
7   8   1.00000
8   9   0.98148
9   10  0.23330
10  11  0.56918
11  12  0.53251
12  13  0.58107
13  14  0.92405
14  15  0.00025
15  16  0.14863
16  17  0.53629
17  18  0.67130
18  19  0.53249
19  20  0.75853
20  21  0.58647
21  22  0.00156
22  23  0.00000
23  24  0.00152
24  25  1.00000

完成合并后,输出如下:首先是133乘以0.98148,然后是47乘以0.00025,然后继续从df2获取更多的值序列,直到最后出现一系列NaN条目。。。在

Out[91]: df1
    A   B   D
0   1   3   0.98148
1   0   9   0.98148
2   0   9   0.98148
3   0   7   0.98148
5   1   21  0.98148
7   1   12  0.98148
...     ...     ...     ...
2592    0   2   NaN
2593    1   17  NaN
2594    1   16  NaN
2596    0   17  NaN
2597    0   6   NaN

你知道这里会发生什么吗?它们都是int64。在

=============

这里有两个csv,其中的数据重现了问题。在

df1: https://owncloud.tu-berlin.de/public.php?service=files&t=2a7d244f55a5772f16aab364e78d3546

df2: https://owncloud.tu-berlin.de/public.php?service=files&t=6fa8e0c2de465cb4f8a3f8890c325eac

复制:

import pandas as pd

df1 = pd.read_csv("../../df1.csv")
df2 = pd.read_csv("../../df2.csv")

df1['D'] = df1[df1.A == 0].merge(df2,left_on='B', right_on='ID', how='left')['value']

Tags: csv数据httpsid示例pandasdfvalue
1条回答
网友
1楼 · 发布于 2024-06-17 08:00:03

这一个有点棘手,这里有两个步骤,首先是只选择数据框中“A”为0的行,然后将“B”和“ID”匹配的另一个数据框合并到该数据框中,但执行“left”合并,然后从中选择“value”列并分配给df:

In [142]:

df['D'] = df[df.A == 0].merge(df1, left_on='B',right_on='ID', how='left')['value']
df
Out[142]:
   A  B   D
0  0  0  62
1  0  2  76
2  1  1 NaN
3  1  1 NaN
4  1  3 NaN

分解这些将显示出正在发生的事情:

^{pr2}$

然后您可以直接分配上述各项:

df['D'] = df[df.A == 0].merge(df1, left_on='B',right_on='ID', how='left')['value']

这是因为它将与左侧的idnex对齐,因此任何丢失的值都将自动被赋值NaN

编辑

另一种对实际数据有效的方法是使用map为您执行查找,map接受dict或series作为参数,并将查找相应的值,在这种情况下,您需要将索引设置为“ID”列,这样可以将df减少为只包含“value”列的df:

df['D'] = df[df.A==0]['B'].map(df1.set_index('ID')['value'])

所以上面的代码像以前一样执行布尔索引,然后在'B'列上调用map,并在我们将索引设置为'ID'之后,在另一个df中查找相应的'Value'。在

更新

我看了你的数据和我的第一个方法,我知道为什么失败了,与左边的df对齐失败,所以你在一个连续的行中得到1192个值,然后剩下的行是NaN直到第2500行。在

如果你把同样的蒙版贴在左手边,效果是这样的:

df1.loc[df1.A==0, 'D'] = df1[df1.A == 0].merge(df2,left_on='B', right_on='ID', how='left')['value']

因此,这将正确地屏蔽左侧的行,并分配合并的结果

相关问题 更多 >