我有两个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
和df2.ID
应该是标识符。
示例输出:
df1
'A' 'B' 'D'
0 0 62
0 2 76
1 1 NaN
1 1 NaN
1 3 NaN
我尝试了以下内容:
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]
有谁知道如何在不需要迭代数据帧的情况下解决问题?
非常感谢!
==============
编辑回复@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']
答案 0 :(得分:3)
这个稍微有点棘手,这里有2个步骤,首先是只选择df中'A'为0的行,然后合并到另一个df,其中'B'和'ID'匹配,但执行''左'合并,然后从中选择'值'列并分配给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
打破这一点将显示正在发生的事情:
In [143]:
# boolean mask on condition
df[df.A == 0]
Out[143]:
A B D
0 0 0 62
1 0 2 76
In [144]:
# merge using 'B' and 'ID' columns
df[df.A == 0].merge(df1, left_on='B',right_on='ID', how='left')
Out[144]:
A B D ID value
0 0 0 62 0 62
1 0 2 76 2 76
完成上述所有操作后,您可以直接分配:
df['D'] = df[df.A == 0].merge(df1, left_on='B',right_on='ID', how='left')['value']
这样可以与左侧的idnex对齐,因此会自动分配任何缺失的值NaN
修改强>
另一种似乎适用于您的真实数据的方法是使用map
为您执行查找,map
接受一个字典或系列作为参数并查找相应的值,在这种情况下,您需要将索引设置为“ID”列,这会将您的df降低为只有“值”列的一个:
df['D'] = df[df.A==0]['B'].map(df1.set_index('ID')['value'])
所以上面像以前一样执行布尔索引,然后在'B'列上调用map
,并在我们在'ID'上设置索引后查找其他df中相应的'Value'。
<强>更新强>
我查看了你的数据和我的第一个方法,我可以看到为什么会失败,左侧df的对齐失败,所以你在连续的行中得到1192个值,然后其余的行是{{1}直到第2500行。
如果你像这样在左侧应用相同的面具,那么工作是什么:
NaN
因此,这会正确遮盖左侧的行并分配合并的结果