是否有一种方法来填充从数据框架的np选择条件?



考虑这样一个查找表:

lower_bound upper_bound category
0       3          6         A
1       10         40        B
2       80         200       C
3       350        600       D
4       900        1500      E

然后,有一个我们需要根据上述条件对元素进行分类的DataFrame:

id    value
0  id_1     20
1  id_2    500
2  id_3   1000

这些项将根据它们的值进行分类,这些值应该在查找表中存在的指定范围之间。所以:

id   value  category
0  id_1    20       B
1  id_2    500      D
2  id_3    1000     E

我尝试了下面的方法,它可以工作:

conditions = []
choices = []
for condition in lookup_df.to_dict('records'):
conditions.append(
(df['value'].between(condition['lower_bound'], condition['upper_bound']))
)
choices.append(condition['category'])

,然后:

df['category'] = np.select(conditions, choices, default=np.nan)

是否有一种方法来生成条件,而不转换为字典和循环查找DataFrame?

您可以使用np.dot:

vals = np.vstack(df['value'].values)
lb = condition['lower_bound'].values <= vals
ub = vals <= condition['upper_bound'].values
df['category'] = np.dot(lb & ub, condition['category'])

输出:

类别th>D

您可以使用pd.merge_asof:

output = pd.merge_asof(df, lookup_df[["lower_bound","category"]], left_on="value", right_on="lower_bound").drop("lower_bound", axis=1)
>>> output
id  value category
0  id_1     20        B
1  id_2    500        D
2  id_3   1000        E

可以使用numpy广播。这个想法是创建一个布尔掩码,为范围each "value"返回True落入lookup_df。然后使用布尔索引选择匹配的值。

vals = df['value'].to_numpy()
msk = (lookup_df[['lower_bound']].to_numpy() < vals) & (vals < lookup_df[['upper_bound']].to_numpy())
df['category'] = lookup_df[['category']].to_numpy().repeat(len(df), axis=1)[msk]

输出:

id  value category
0  id_1     20        B
1  id_2    500        D
2  id_3   1000        E

如果您想要NaN值在任何范围之外的值,dot产品将在这里工作得最好(这与@Corralien的解决方案完全相同):

vals = df[['value']].to_numpy()
msk = (lookup_df['lower_bound'].to_numpy() < vals) & (vals < lookup_df['upper_bound'].to_numpy())
df = df.assign(category=msk.dot(lookup_df['category'])).replace('', float('nan'))

最新更新