假设我在数据框中有一个“ user_age”列,并且通过类似以下方式创建了“ user_age_bin”:
df['user_age_bin']= pd.cut(df['user_age'], bins=[10, 15, 20, 25,30])
然后,我使用“ user_age_bin”功能构建机器学习模型。
接下来,我得到了一条记录,需要将其放入模型并进行预测。我不想使用user_age
,因为模型使用了user_age_bin
。因此,如何将user_age
值(例如28)转换为user_age_bin
?我知道我可以创建这样的函数:
def assign_bin(age):
if age < 10:
return '<10'
elif age< 15:
return '10-15'
... etc. etc.
然后执行:
user_age_bin = assign_bin(28)
但是这种解决方案一点都不优雅。我想一定有更好的方法吧?
编辑:我更改了代码并添加了明确的bin范围。 Edit2:编辑了措辞,希望现在问题更清楚了。
答案 0 :(得分:1)
双重列表理解有点丑陋,但似乎可以完成工作。
设置:
import pandas as pd
import numpy as np
np.random.seed(42)
bins = [10, 15, 20, 25, 30, np.Inf]
labels = bins[1:]
ages = np.random.randint(10, 35, 10)
df = pd.DataFrame({"user_age": ages})
df["user_age_bin"] = pd.cut(df["user_age"], bins=bins, labels=labels)
print(df)
出局:
user_age user_age_bin
0 16 20.0
1 29 30.0
2 24 25.0
3 20 20.0
4 17 20.0
5 30 30.0
6 16 20.0
7 28 30.0
8 32 inf
9 20 20.0
分配:
# `new_ages` is what you want to assign labels to, used `ages` for simplicity
new_ages = ages
ids = [np.argmax([age <= x for x in labels]) for age in new_ages]
assigned_labels = [labels[i] for i in ids]
print(pd.DataFrame({"new_ages": new_ages, "assigned_labels": assigned_labels, "user_age_bin": df["user_age_bin"]}))
出局:
new_ages assigned_labels user_age_bin
0 16 20.0 20.0
1 29 30.0 30.0
2 24 25.0 25.0
3 20 20.0 20.0
4 17 20.0 20.0
5 30 30.0 30.0
6 16 20.0 20.0
7 28 30.0 30.0
8 32 inf inf
9 20 20.0 20.0
答案 1 :(得分:1)
tl; dr:np.digitize
是一个很好的解决方案。
在阅读了这里的所有评论和答案以及更多谷歌搜索之后,我认为我得到了一个令我非常满意的解决方案。谢谢大家!
设置
import pandas as pd
import numpy as np
np.random.seed(42)
bins = [0, 10, 15, 20, 25, 30, np.inf]
labels = bins[1:]
ages = list(range(5, 90, 5))
df = pd.DataFrame({"user_age": ages})
df["user_age_bin"] = pd.cut(df["user_age"], bins=bins, labels=False)
# sort by age
print(df.sort_values('user_age'))
输出:
user_age user_age_bin
0 5 0
1 10 0
2 15 1
3 20 2
4 25 3
5 30 4
6 35 5
7 40 5
8 45 5
9 50 5
10 55 5
11 60 5
12 65 5
13 70 5
14 75 5
15 80 5
16 85 5
分配类别:
# a new age value
new_age=30
# use this right=True and '-1' trick to make the bins match
print(np.digitize(new_age, bins=bins, right=True) -1)
输出:
4
答案 2 :(得分:0)
您可以尝试类似的操作:
bins=[10, 15, 20, 25, 30]
labels = [f'<{bins[0]}', *(f'{a}-{b}' for a, b in zip(bins[:-1], bins[1:])), f'{bins[-1]}>']
pd.cut(df['user_age'], bins=bins, labels=labels)
请注意,如果您使用的是python<3.7
,则应使用类似语法的格式替换f-string。
答案 3 :(得分:0)
您不能将字符串放入模型中,因此需要创建一个映射并跟踪它,或者创建一个单独的columnn以便以后使用
variable = shared_var.get()
对于模型,您将保留def apply_age_bin_numeric(value):
if value <= 10:
return 1
elif value > 10 and value <= 20:
return 2
elif value > 21 and value <= 30:
return 3
etc....
def apply_age_bin_string(value):
if value <= 10:
return '<=10'
elif value > 10 and value <= 20:
return '11-20'
elif value > 21 and value <= 30:
return '21-30'
etc....
df['user_age_bin_numeric']= df['user_age'].apply(apply_age_bin_numeric)
df['user_age_bin_string']= df['user_age'].apply(apply_age_bin_string)
并放下user_age_bin_numeric
在数据进入模型之前,先保存包含两个字段的数据副本。这样,如果您想显示预测而不是数字分类,则可以将预测与分类字段的字符串版本匹配。