Python 如何一次对数据中的所有列进行分类?(使所有值变为高、中、低)
我试图将数据集中的所有值转换为分类值,我希望所有数值根据其分位数值分类为低、平均或高 因此,如果该值低于该系列的25%,则将其转换为“低” 我尝试使用assign,然后应用了我提供的函数:Python 如何一次对数据中的所有列进行分类?(使所有值变为高、中、低),python,pandas,dataframe,categorical-data,Python,Pandas,Dataframe,Categorical Data,我试图将数据集中的所有值转换为分类值,我希望所有数值根据其分位数值分类为低、平均或高 因此,如果该值低于该系列的25%,则将其转换为“低” 我尝试使用assign,然后应用了我提供的函数: def turn_into_categorical(row): quantile_level = [.25, .5, .75] for r in row: cut = refugees_T_F_V_P_full_data.r.quantile(quantile_level)
def turn_into_categorical(row):
quantile_level = [.25, .5, .75]
for r in row:
cut = refugees_T_F_V_P_full_data.r.quantile(quantile_level)
if r >= cut[.75]:
return "High"
elif r >= cut[.25] and r < cut[0.75]:
return "Average"
else:
return "Low"
refugees_T_F_V_P_full_data.apply(turn_into_categorical, axis = 1)
预期成果:(举例)
一个想法是使用
pd.DataFrame.quantile
和pd.Series.cut
:
cats = ['Low', 'Medium', 'High']
quantiles = df.iloc[:, 2:].quantile([0, 0.25, 0.75, 1.0])
for col in df.iloc[:, 2:]:
bin_edges = quantiles[col]
# special case situations where all values are equal
if bin_edges.nunique() == 1:
df[col] = 'Low'
else:
df[col] = pd.cut(df[col], bins=bin_edges, labels=cats, include_lowest=True)
结果:
print(df)
Year Month CentralEquatoria EasternEquatoria Gogrial Jonglei
0 2014 10 Medium Low Low Low
1 2014 11 Low Medium Low High
2 2014 12 Low Medium Low High
3 2015 1 Medium Medium Low Low
4 2015 2 Medium Medium Low High
5 2015 3 Medium Medium Low Medium
6 2015 4 Low Low Low Medium
7 2015 5 Medium Low Low Medium
8 2015 6 Low Low Low Medium
9 2015 7 High Medium Low Medium
10 2015 8 High High Low Medium
11 2015 9 High Low Low Medium
12 2015 10 High Low Low Low
13 2015 11 Medium Medium Low High
14 2015 12 Medium High Low Low
看起来像你想要的,这正是你想要的。从文档中:
基于分位数的离散化函数
因此,您可以沿着数据帧的列pd.qcut
从Central Equatoria
开始,指定要使用q=[0,0.25,0.75,1.0]来存储序列的分位数。
df.loc[:,'Central Equatoria':].apply(lambda x: pd.qcut(x, q=[0, 0.25, 0.75, 1.0],
labels =['low','medium','high'])
if not x.nunique() == 1 else 'low'))
输出
使用pd.cut()
和df.apply()
:
最终使用最古老的方式:
new_df = pd.DataFrame()
name_list = list(df)
for name in name_list:
if name != 'Year' and name != 'Month':
new_row = []
quantiles = df[name].quantile([.25, .5, .75])
row_list = df[name].tolist()
for i, value in enumerate(row_list):
if value < quantiles[.25]:
new_row.append("Low")
elif value < quantiles[.75] and value >= quantiles[.25]:
new_row.append("Average")
else:
new_row.append("High")
series = pd.Series(new_row)
new_df[name] = series.values
new_df.head()
new_df=pd.DataFrame()
名称\列表=列表(df)
对于名称列表中的名称:
如果名称!='年份和名称!='月份:
新_行=[]
分位数=df[name]。分位数([.25、.5、.75])
行列表=df[name].tolist()
对于i,枚举中的值(行列表):
如果值<分位数[.25]:
新增行。追加(“低”)
elif值<分位数[.75]和值>=分位数[.25]:
新增行。追加(“平均值”)
其他:
新增行。追加(“高”)
系列=局部放电系列(新行)
new_df[name]=series.values
新(财务总监)
作为评论,这是一个写得很好的问题,有一个有趣的问题-谢谢!如果OP愿意使用int标签而不是字符串,我想我们可以将其矢量化。我只是想敲定一个idea@roganjosh,pd.cut
我相信它是完全矢量化的,最后的“字符串”系列实际上是有效的分类,即由整数数组支持。啊,噗,我看到了for
循环,并以错误的方式读了它!我要的是np.digitalize
。您说得对。我已经尝试了该代码,但它返回的错误与我尝试@yatu的代码ValueError:Bin边必须是唯一的:数组([0,0,5,26])。您可以通过设置“duplicates”(重复)kwarg来删除重复边
比我的解决方案更好:)。。基本上,这结合了分位数
和切割
方法。是的,它直接使用分位数信息进行分类。谢谢:)我试图实现您的代码和@jpp的代码,但是pd.qcut函数似乎总是返回错误ValueError:(“Bin边必须是唯一的:数组([0,0,2,7])。\n您可以通过设置“duplicates”kwarg来删除重复边,“发生在北加扎勒河的索引中”)
我试图从这里搜索解决方案,并添加了一个参数duplicates='drop'
,但它仍然返回ValueError:(“垃圾箱标签必须比垃圾箱边缘的数量少一个”,“发生在北加扎勒河的索引中”)
完整的代码在这里难民数据。iloc[:,2:。应用(lambda x:pd.qcut(x,duplicates='drop',q=[0,0.25,0.75,1.0],标签=['low','medium','high'])如果不是x.nunique()==1,则为'low'
df.loc[:,'Central Equatoria':].apply(lambda x: pd.qcut(x, q=[0, 0.25, 0.75, 1.0],
labels =['low','medium','high'])
if not x.nunique() == 1 else 'low'))
Central Equatoria Eastern Equatoria Gogrial Jonglei
0 medium low low low
1 low medium low high
2 low medium low high
3 medium medium low low
4 medium medium low high
5 medium medium low medium
6 low low low medium
7 medium low low medium
8 low low low medium
9 high medium low medium
10 high high low medium
11 high low low medium
12 high low low low
13 medium medium low high
14 medium high low low
df.iloc[:,2:]=df.iloc[:,2:].apply(lambda x:pd.cut(x, 3, labels=['Low','Med','High']), axis=1)
Year Month Central_Equatoria Eastern_Equatoria Gogrial Jonglei
0 2014 10 High Low Low Med
1 2014 11 Low Low Low High
2 2014 12 Low Med Low High
3 2015 1 High Low Low Med
4 2015 2 Med Med Low High
5 2015 3 High Med Low High
new_df = pd.DataFrame()
name_list = list(df)
for name in name_list:
if name != 'Year' and name != 'Month':
new_row = []
quantiles = df[name].quantile([.25, .5, .75])
row_list = df[name].tolist()
for i, value in enumerate(row_list):
if value < quantiles[.25]:
new_row.append("Low")
elif value < quantiles[.75] and value >= quantiles[.25]:
new_row.append("Average")
else:
new_row.append("High")
series = pd.Series(new_row)
new_df[name] = series.values
new_df.head()