¿Qué es una buena heurística para detectar si una columna en un pandas.DataFrame es categórica?

He estado desarrollando una herramienta que procesa automáticamente los datos en formato pandas.DataFrame. Durante este paso de preprocesamiento, quiero tratar los datos continuos y categóricos de manera diferente. En particular, quiero poder aplicar, por ejemplo, un OneHotEncoder solo a los datos categóricos.

Ahora, supongamos que se nos proporciona un pandas.DataFrame y no tenemos otra información sobre los datos en el DataFrame. ¿Qué es una buena heurística para determinar si una columna en los pandas.DataFrame es categórica?

Mis pensamientos iniciales son:

1) Si hay cadenas en la columna (por ejemplo, el tipo de datos de la columna es un object ), es muy probable que la columna contenga datos categóricos.

2) Si algún porcentaje de los valores en la columna es único (por ejemplo,> = 20%), es muy probable que la columna contenga datos continuos.

He encontrado que 1) funciona bien, pero 2) no ha funcionado muy bien. Necesito mejores heurísticas. Como resolverías este problema?

Edit: alguien me pidió que explique por qué 2) no funcionó bien. Hubo algunos casos de prueba en los que todavía teníamos valores continuos en una columna, pero no había muchos valores únicos en la columna. La heurística en 2) obviamente falló en ese caso. También hubo problemas en los que teníamos una columna categórica que tenía muchos, muchos valores únicos, por ejemplo, nombres de pasajeros en el conjunto de datos del Titanic. El mismo problema de error de clasificación de columna allí.

Aquí hay un par de enfoques:

  1. Encuentre la relación entre el número de valores únicos y el número total de valores únicos. Algo como lo siguiente

     likely_cat = {} for var in df.columns: likely_cat[var] = 1.*df[var].nunique()/df[var].count() < 0.05 #or some other threshold 
  2. Compruebe si los n valores principales superiores representan más de una cierta proporción de todos los valores

     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 

El Enfoque 1) generalmente me ha funcionado mejor que el Enfoque 2). Pero el enfoque 2) es mejor si hay una "distribución de cola larga", donde un pequeño número de variables categóricas tienen alta frecuencia mientras que un gran número de variables categóricas tienen baja frecuencia.

Hay muchos lugares donde podría “robar” las definiciones de formatos que se pueden convertir como “número”. ##, # e- # sería uno de esos formatos, solo para ilustrar. Tal vez puedas encontrar una biblioteca para hacerlo. Intento convertir todo en números primero y lo que queda, bueno, no hay otra manera más que mantenerlos como categóricos.

Creo que la verdadera pregunta aquí es si le gustaría molestar al usuario de vez en cuando o fallar en silencio de vez en cuando.

Si no le importa molestar al usuario, tal vez detectar la ambigüedad y generar un error sea el camino a seguir.

Si no te importa fallar en silencio, entonces tu heurística está bien. No creo que encuentres nada que sea significativamente mejor. Supongo que podrías convertir esto en un problema de aprendizaje si realmente lo deseas. Descargue un conjunto de conjuntos de datos, suponga que son en conjunto una representación decente de todos los conjuntos de datos en el mundo y adiestre en función de las características de cada conjunto de datos / columna para predecir categóricos frente a continuos.

Pero claro que al final nada puede ser perfecto. Por ejemplo, ¿la columna [1, 8, 22, 8, 9, 8] se refiere a las horas del día oa las razas de perros?

He estado pensando en un problema similar y cuanto más lo considero, parece que este es un problema de clasificación que podría beneficiarse de la capacitación de un modelo.

Apuesto a que si examinó un conjunto de conjuntos de datos y extrajo estas características para cada columna / pandas. Serie:

  • % flotantes: porcentaje de valores que son flotantes
  • % int: porcentaje de valores que son números enteros
  • % cadena: porcentaje de valores que son cadenas
  • % cadena única: número de valores de cadena únicos / número total
  • % de enteros únicos: número de valores enteros únicos / número total
  • valor numérico medio (valores no numéricos considerados 0 para esto)
  • desviación estándar de valores numéricos

y entrenó un modelo, podría ser bastante bueno para inferir tipos de columnas, donde los valores de salida posibles son: categórico, ordinal, cuantitativo.

Nota al margen: en lo que respecta a una serie con un número limitado de valores numéricos, parece que el problema interesante sería determinar categórico versus ordinal; no hace daño pensar que una variable es ordinal si resulta ser cuantitativa, ¿no? Los pasos de preprocesamiento codificarían los valores ordinales numéricamente de todos modos sin una encoding instantánea.

Un problema relacionado que es interesante: dado un grupo de columnas, ¿puedes decir si ya están codificadas de forma instantánea? Por ejemplo, en el concurso Kaggle de predicción de tipo de cubierta forestal, usted sabría automáticamente que el tipo de suelo es una única variable categórica.

En la OMI, la estrategia opuesta, identificar categorías es mejor porque depende de qué se trata la información. Técnicamente, los datos de direcciones se pueden considerar como datos categóricos no ordenados, pero generalmente no los usaría de esa manera.

Para datos de encuestas, una idea sería buscar escalas Likert, por ejemplo, valores de 5 a 8, ya sea cadenas (que probablemente necesiten niveles codificados (y traducidos) para buscar “bueno”, “malo”, “. De acuerdo. “, “muy. *”, …) o valores int en el rango 0-8 + NA.

Los países y esas cosas también podrían ser identificables …

Los grupos de edad (“. -. “) También podrían funcionar.

Puede definir qué tipos de datos cuentan como numéricos y luego excluir las variables correspondientes

Si el dataframe inicial es df:

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