我一直在开发一种自动预处理pandas.DataFrame格式数据的工具。在此预处理步骤中,我希望以不同方式处理连续和分类数据。特别是,我希望能够将例如OneHotEncoder应用于仅分类数据。
现在,让我们假设我们提供了一个pandas.DataFrame,并且没有关于DataFrame中数据的其他信息。用于确定pandas.DataFrame中的列是否属于分类的优秀启发式算法是什么?
我最初的想法是:
1)如果列中有字符串(例如,列数据类型为object
),则该列很可能包含分类数据
2)如果列中某些百分比的值是唯一的(例如,> = 20%),那么该列很可能包含连续数据
我发现1)
工作正常,但2)
并没有很好地发挥作用。我需要更好的启发式方法。你会如何解决这个问题?
编辑:有人要求我解释为什么2)
效果不佳。在某些测试案例中,我们仍然在列中有连续值,但列中的唯一值不多。在这种情况下,2)
中的启发式显然失败了。还有一些问题,我们有一个分类列,其中有许多独特的值,例如泰坦尼克号数据集中的乘客名称。那里的列类型错误分类问题。
答案 0 :(得分:18)
以下是两种方法:
查找唯一值的数量与唯一值的总数之比。类似于以下内容
likely_cat = {} for var in df.columns: likely_cat[var] = 1.*df[var].nunique()/df[var].count() < 0.05 #or some other threshold
检查前n个唯一值是否占所有值的一定比例
top_n = 10 likely_cat = {} for var in df.columns: likely_cat[var] = 1.*df[var].value_counts(normalize=True).head(top_n).sum() > 0.8 #or some other threshold
方法1)通常比方法2)更好地为我工作。但是如果存在“长尾分布”,则方法2)会更好,其中少数分类变量具有高频率,而大量分类变量具有低频率。
答案 1 :(得分:2)
在很多地方,你可以“偷”&#34;格式的定义可以转换为&#34; number&#34;。 ##,#e-#将是这种格式之一,只是为了说明。也许你能够找到一个库来做到这一点。 我试着先把所有东西都用在数字上,剩下的就是剩下的,好吧,除了让它们成为绝对之外别无他法。
答案 2 :(得分:1)
IMO相反的策略,识别分类更好,因为它取决于数据的含义。技术上可以将地址数据视为无序的分类数据,但通常我不会这样使用它。
对于调查数据,一个想法是寻找李克特量表,例如: 5-8个值,可以是字符串(可能需要硬编码(和翻译)级别来查找&#34;好&#34;,&#34;坏&#34;,&#34;。同意。< / em>&#34;,&#34;非常。*&#34;,...)或0-8范围内的int值+ NA。
国家和其他类似的东西也可以识别......
年龄组(&#34;。 - 。&#34;)也可能有效。
答案 3 :(得分:1)
我认为这里真正的问题是你是想偶尔打扰一下用户还是偶尔会默默地失败。
如果您不介意打扰用户,可能会检测出歧义并提出错误是可行的方法。
如果你不介意默默地失败,那么你的启发式方法是可以的。我认为你不会发现任何明显更好的东西。如果你真的想,你可以把它变成一个学习问题。下载一堆数据集,假设它们共同代表了世界上所有数据集,并根据每个数据集/列上的特征进行训练,以预测分类与连续。
但当然最终没有什么是完美的。例如。列[1,8,22,8,9,8]是指一天中的小时数还是狗品种?
答案 4 :(得分:1)
我一直在考虑类似的问题而且我考虑的越多,似乎这本身就是一个可以从训练模型中受益的分类问题。
我打赌如果你检查了一堆数据集并为每个列/ pandas提取了这些功能。系列:
并训练了一个模型,它可以很好地推断出列类型,其中可能的输出值是:分类,序数,定量。
旁注:就数字数量有限的系列而言,似乎有趣的问题是确定分类与序数;如果变量是定量的,那么认为变量是有序的并不会有什么害处?无需单热编码,预处理步骤将以数字方式对序数值进行编码。
一个有趣的相关问题:给定一组列,你能判断它们是否已经是单热编码的吗?例如,在森林覆盖类型预测变量竞赛中,您会自动知道土壤类型是一个分类变量。
答案 5 :(得分:1)
您可以定义哪些数据类型作为数字计数,然后排除相应的变量
如果初始数据帧为df:
numerics = ['int16', 'int32', 'int64', 'float16', 'float32', 'float64']
dataframe = df.select_dtypes(exclude=numerics)
答案 6 :(得分:0)
我一直在研究这个问题,认为分享我的东西可能有用。这基于@Rishabh Srivastava的答案。
import pandas as pd
def remove_cat_features(X, method='fraction_unique', cat_cols=None, min_fraction_unique=0.05):
"""Removes categorical features using a given method.
X: pd.DataFrame, dataframe to remove categorical features from."""
if method=='fraction_unique':
unique_fraction = X.apply(lambda col: len(pd.unique(col))/len(col))
reduced_X = X.loc[:, unique_fraction>min_fraction_unique]
if method=='named_columns':
non_cat_cols = [col not in cat_cols for col in X.columns]
reduced_X = X.loc[:, non_cat_cols]
return reduced_X
然后可以调用此函数,将pandas df命名为X
,并且可以删除命名的分类列,也可以选择删除具有较少唯一值(由min_fraction_unique
指定的列)的列。 )。