簡體   English   中英

Pandas使用兩個數據幀進行布爾索引

[英]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.Bdf2.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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM