Python 检测pandas.DataFrame中的列是否为分类列的好方法是什么?

Python 检测pandas.DataFrame中的列是否为分类列的好方法是什么?,python,pandas,scikit-learn,Python,Pandas,Scikit Learn,我一直在开发一个自动预处理pandas.DataFrame格式数据的工具。在这个预处理步骤中,我希望以不同的方式处理连续数据和分类数据。特别是,我希望能够将OneHotEncoder应用于分类数据 现在,假设我们提供了pandas.DataFrame,并且没有关于DataFrame中数据的其他信息。确定pandas.DataFrame中的列是否为分类列时,使用什么好的启发式方法 我最初的想法是: 1) 如果列中有字符串(例如,列数据类型为object),则该列很可能包含分类数据 2) 如果列中某

我一直在开发一个自动预处理pandas.DataFrame格式数据的工具。在这个预处理步骤中,我希望以不同的方式处理连续数据和分类数据。特别是,我希望能够将OneHotEncoder应用于分类数据

现在,假设我们提供了pandas.DataFrame,并且没有关于DataFrame中数据的其他信息。确定pandas.DataFrame中的列是否为分类列时,使用什么好的启发式方法

我最初的想法是:

1) 如果列中有字符串(例如,列数据类型为
object
),则该列很可能包含分类数据

2) 如果列中某些百分比的值是唯一的(例如>=20%),则该列很可能包含连续数据

我发现
1)
效果很好,但
2)
效果不太好。我需要更好的启发法。你将如何解决这个问题


编辑:有人要求我解释为什么
2)
效果不好。在一些测试案例中,我们在一列中仍然有连续的值,但在该列中没有许多唯一的值。在这种情况下,
2)
中的启发式显然失败了。还有一个问题是,我们有一个分类列,其中有许多、许多唯一的值,例如,泰坦尼克号数据集中的乘客姓名。同样的列类型错误分类问题。

在相反的策略中,识别类别更好,因为它取决于数据的内容。从技术上讲,地址数据可以被认为是无序的分类数据,但通常我不会这样使用它

对于调查数据,一个想法是寻找Likert量表,例如5-8个值,字符串(可能需要硬编码(和翻译)级别以查找“好”、“坏”、“同意”、“非常。*”或0-8范围+NA的int值

国家和类似的事物也可能是可识别的


年龄组(“.-”)也可能起作用。

以下是几种方法:

  • 查找唯一值的数目与唯一值总数的比率。类似于下面的内容


  • 方法1)通常比方法2)更适合我。但是,如果存在“长尾分布”,则方法2)更好,其中少量分类变量具有高频率,而大量分类变量具有低频率。

    在许多地方,您可以“窃取”可转换为“数字”的格式定义。##e-#就是这样一种格式,只是为了举例说明。也许你能找到一个图书馆这样做。
    我试着先把所有的东西都转换成数字,剩下的是什么,好吧,除了保持它们的分类之外,没有其他办法了。

    我认为这里真正的问题是,你是想偶尔打扰用户一次,还是偶尔默默地失败一次

    如果你不介意打扰用户,也许检测歧义并提出错误是最好的方法

    如果你不介意默默地失败,那么你的启发式就可以了。我认为你不会找到比这更好的东西。如果你真的想,我想你可以把这变成一个学习问题。下载一组数据集,假设它们是世界上所有数据集的一个整体,并根据每个数据集/列的特征进行训练,以预测分类与连续


    当然,最终没有什么是完美的。例如,列(1, 8, 22,8, 9, 8)指的是一天中的几个小时还是狗的品种?

    < P>我一直在思考一个类似的问题,而且我认为它似乎是一个分类问题,它可以从一个模型中受益。p> 我敢打赌,如果您检查了一组数据集,并为每列/每只熊猫提取了这些特征。系列:

    • %浮动:浮动值的百分比
    • %int:为整数的值的百分比
    • %字符串:为字符串的值的百分比
    • %唯一字符串:唯一字符串值的数目/总数
    • %唯一整数:唯一整数值的数目/总数
    • 平均数值(非数值视为0)
    • 数值的标准偏差
    通过训练一个模型,它可以很好地推断列类型,其中可能的输出值是:分类的、有序的、定量的

    旁注:对于数量有限的数值序列来说,有趣的问题似乎是确定分类与序数;如果一个变量被证明是定量的,那么认为它是有序的并没有什么坏处?预处理步骤将对序数值进行数字编码,而无需一次热编码


    有一个相关的问题很有趣:给定一组列,您能否判断它们是否已经是一个热编码的列?例如,在森林覆盖类型预测kaggle竞赛中,您将自动知道土壤类型是一个单一的分类变量。

    您可以定义哪些数据类型算作数字,然后排除相应的变量

    如果初始数据帧为df:

    numerics = ['int16', 'int32', 'int64', 'float16', 'float32', 'float64']
    dataframe = df.select_dtypes(exclude=numerics)
    

    我一直在看这个,觉得分享我所拥有的可能有用。这建立在@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
    

    然后,您可以调用此函数,给出一个名称为
    X
    ,您可以删除命名的分类列,也可以选择删除具有少量唯一值的列(由
    min\u fraction\u unique
    指定)。

    我相信这个问题几乎完全没有定义。世界上所有数据集的分布情况如何?例如,对于邮政服务或电话簿,你的规则1失败得很惨。试着区分数字数据和分类数据。@Barmaley。
    numerics = ['int16', 'int32', 'int64', 'float16', 'float32', 'float64']
    dataframe = df.select_dtypes(exclude=numerics)
    
    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