使用 table 在 DataFrame 中编码值,在 python 中使用间隔描述

coding values in DataFrame using table with interval description in python

我在 pandas df1

中有一个 table
id   value
1    1500
2    -1000
3    0   
4    50000  
5    50   

我在数据框 df2 中还有另一个 table,它包含组的上边界,所以基本上每一行代表从前一个边界到当前边界的间隔(第一个间隔是“<0”) :

group   upper
0       0
1       1000
2       NaN

我应该如何使用 df2 的间隔从 df 获取相关组的价值?我不能使用联接、合并等,因为此联接的规则应该像 "if value is between previous upper and current upper" 而不是 "if value equals something"。我发现的唯一方法是使用带有 df.apply() 的预定义函数(其中也有一个带有 interval_flag==False 的分类值的情况):

def values_to_group(x, interval_flag, groups_def):
    if interval_flag==True:
        for ind, gr in groups_def.sort_values(by='group').iterrows():
            if x<gr[1]:
                return gr[0]
            elif math.isnan(gr[1]) == True:
                return gr[0]
    else:
        for ind, gr in groups_def.sort_values(by='group').iterrows():
            if x in gr[1]:
                return gr[0]

是否有easier/more最佳方法?

预期的输出应该是这样的:

id   value   group
1    1500    2
2    -1000   0
3    0       1
4    50000   2
5    50      1

我建议使用 cut 和排序 df2DataFrame by sorted upper 并将最后一个 NaN 替换为 np.inf:

df2 = pd.DataFrame({'group':[0,1,2], 'upper':[0,1000,np.nan]})
df2 = df2.sort_values('upper')
df2['upper'] = df2['upper'].replace(np.nan, np.inf)
print (df2)
   group        upper
0      0     0.000000
1      1  1000.000000
2      2          inf

#added first bin -np.inf
bins = np.insert(df2['upper'].values, 0, -np.inf)
df1['group'] = pd.cut(df1['value'], bins=bins, labels=df2['group'], right=False)
print (df1)
   id  value group
0   1   1500     2
1   2  -1000     0
2   3      0     1
3   4  50000     2
4   5     50     1

这是使用 numpy.digitize 的解决方案。您唯一的任务是构建 binsnames 输入列表,这应该可以通过输入数据框实现。

import pandas as pd, numpy as np

df = pd.DataFrame({'val': [99, 53, 71, 84, 84]})
df['ratio'] = df['val']/ df['val'].shift() - 1

bins = [-np.inf, 0, 0.2, 0.4, 0.6, 0.8, 1.0, np.inf]
names = ['<0', '0.0-0.2', '0.2-0.4', '0.4-0.6', '0.6-0.8', '0.8-1.0', '>1']

d = dict(enumerate(names, 1))

df['Bucket'] = list(map(d.get, np.digitize(df['ratio'], bins)))

print(df)

   val     ratio   Bucket
0   99       NaN     None
1   53 -0.464646       <0
2   71  0.339623  0.2-0.4
3   84  0.183099  0.0-0.2
4   84  0.000000  0.0-0.2