【发布时间】:2021-03-02 06:07:36
【问题描述】:
给定三个数据框,一个包含用户数据,第二个包含数据分箱,第三个是类别名称,如下所示:
klasses_df = pd.DataFrame([[1, 'Sad'],
[7, 'Regular'],
[13, 'Happy'],
[42, 'Magical']],
columns=['klass', 'mood'])
bins_df = pd.DataFrame([[0.0, 3.0, 1],
[3.0, 6.0, 7],
[6.0, 8.0, 13]],
columns=['lower', 'upper', 'klass'])
person_df = pd.DataFrame([['John', 1.5],
['Mary', 3.6],
['Paul', 7.2],
['Josh', 5.7],
['Phil', 9.9]],
columns=['name', 'feeling'])
我想扩展person_df(或创建一个新的数据框),在那里可以找到正确的klass_id 和mood。例如在person_df 的第一行,John 的感觉在1.5,检查bins_df 我们可以看到它在范围第一范围[0, 3] 因此在klass 1。查看klasses_df,我们发现klass_id1 是Sad。这将使与 Jonh 相关的最后/新行成为John, 1.5, 1, 'Sad'。
为了实现这一点,我创建了两个辅助功能:
def find_klass_from_feeling(feeling, bin_data):
values = bin_data.values
klass = values[(values[:,0] <= feeling) & (feeling < values[:,1])][:,2]
if len(klass) == 0:
return 0
else:
return int(klass.flatten()[0])
def find_mood_from_class(klass, klasses_data):
if klass == 0:
return None
retval = klasses_df[klasses_df['klass'] == klass]['mood'].iloc[0]
return retval
我称它们为:
final_df = person_df.copy()
klss = []
moods = []
for idx, row in person_df.iterrows():
kls = find_klass_from_feeling(row['feeling'], bins_df)
mood = find_mood_from_class(kls, klasses_df)
klss.append(kls)
moods.append(mood)
final_df['klass'] = klss
final_df['mood'] = moods
它有效,但似乎完全错误,因为我相信,pandas 有一些更合适的方法来处理它。我尝试使用apply 和applymap 没有成功。
欢迎任何提示。
【问题讨论】:
-
查看“非 equi 连接”,例如此处讨论:stackoverflow.com/questions/50573457/…
-
您可以将分箱重写为不同的格式,还是必须是这个数据框(即,如果分箱可以在列表中,这更易于管理)?另外,Phil 的分数超出 bin 范围会怎样?
-
另外,您的垃圾箱在开始和结束时具有相同的值。例如,如果一个人落在 3 号上,他们应该属于 1 号箱还是 7 号箱?
-
lower <= value < upper求解器。它需要相同的值,因为无法表示限制。