使用 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
和排序 df2
的 DataFrame
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
的解决方案。您唯一的任务是构建 bins
和 names
输入列表,这应该可以通过输入数据框实现。
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
我在 pandas df1
中有一个 tableid 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
和排序 df2
的 DataFrame
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
的解决方案。您唯一的任务是构建 bins
和 names
输入列表,这应该可以通过输入数据框实现。
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