Pandas table 查找

Pandas table lookup

我有一个 pandas 查找 table 看起来像这样

Grade   Lower_Boundary  Upper_Boundary
1   -110    -96
2   -96 -91
3   -91 -85
4   -85 -81
5   -81 -77
6   -77 -72
7   -72 -68
8   -68 -63
9   -63 -58
10  -58 -54
11  -54 -50
12  -50 -46
13  -46 -42
14  -42 -38
15  -38 -34
16  -34 -28
17  -28 -18
18  -18 -11
19  -11 -11
20  -11 -9

我有另一个 pandas 数据框,看起来包含分数。我想通过查找 table 将 'Grade' 分配给分数列。因此,根据分数落在下边界和上边界的哪个区间,应该从查找中的那一行分配分数 table。有没有办法不用输入一堆 if then else 语句就可以做到这一点?我只想到 excel 的索引匹配。

Score   Grade
-75 6
-75 6
-60 9
-66 8
-66 8
-98 1
-60 9
-82 4
-70 7
-60 9
-60 9
-60 9
-56 10
-70 7
-70 7
-70 7
-66 8
-56 10
-66 8
-66 8

一个在线解决方案(我称你的查找table lookup):

df['Score'].apply(lambda score: lookup['Grade'][(lookup['Lower_Boundary'] <= score) & (lookup['Upper_Boundary'] > score)].values[0])

解释:

对于给定的分数,以下是查找分数的方法:

score = -75
match = (lookup['Lower_Boundary'] <= score) & (lookup['Upper_Boundary'] > score)
grade = lookup['Grade'][match]

这是一个长度为1的return序列。你可以得到它的值,例如:

grade.values[0]

您需要做的就是apply上面的分数栏。如果你想要单行,请使用 lambda 函数:

df['Score'].apply(lambda score: lookup['Grade'][(lookup['Lower_Boundary'] <= score) & (lookup['Upper_Boundary'] > score)].values[0])

否则下面的内容会更具可读性:

def lookup_grade(score):
    match = (lookup['Lower_Boundary'] <= score) & (lookup['Upper_Boundary'] > score)
    grade = lookup['Grade'][match]
    return grade.values[0]

df['Score'].apply(lookup_grade)

这种方法还可以更轻松地处理未找到匹配项的情况。

一个选项是 conditional_join from pyjanitor,也包括重叠间隔:

# pip install pyjanitor
import pandas as pd
import janitor

(df2
.conditional_join(
    df1, 
    ('Score', 'Lower_Boundary', '>='), 
    ('Score', 'Upper_Boundary', '<='), 
    how = 'left')
.loc[:, ['Score', 'Grade']]
)

    Score  Grade
0     -75      6
1     -75      6
2     -60      9
3     -66      8
4     -66      8
5     -98      1
6     -60      9
7     -82      4
8     -70      7
9     -60      9
10    -60      9
11    -60      9
12    -56     10
13    -70      7
14    -70      7
15    -70      7
16    -66      8
17    -56     10
18    -66      8
19    -66      8

您也可以使用 pd.IntervalIndex 实现此目的,而且速度应该更快,尤其是当您的数据没有重叠间隔时。