[英]Pandas Boolean indexing with two dataframes
我有兩個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
指定為df1的新列D
,但是當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']
稍微有點棘手,這里有2個步驟,首先是只選擇df中'A'為0的行,然后合並到另一個df,'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
打破這種情況將顯示正在發生的事情:
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
接受dict或系列作為參數並查找相應的值,在這種情況下您需要將索引設置為' ID'列,僅使用'Value'列將df降低為1:
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']
因此,這會正確遮蓋左側的行並分配合並的結果
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.