2010-04-19 8 views
18

Pregunta breve: ¿Cómo puedo detectar automáticamente si un archivo CSV tiene encabezados en la primera fila?Detección automática de la presencia de encabezados CSV en un archivo

Detalles: He escrito un pequeño motor de análisis CSV que coloca los datos en un objeto al que puedo acceder como (aproximadamente) una base de datos en memoria. El código original se escribió para analizar CSV de terceros con un formato predecible, pero me gustaría poder usar este código de manera más general.

Estoy tratando de encontrar una manera confiable de detectar automáticamente la presencia de encabezados CSV, por lo que el script puede decidir si usar la primera fila del archivo CSV como claves/nombres de columna o comenzar a analizar datos inmediatamente. Como todo lo que necesito es una prueba booleana, podría especificar fácilmente un argumento después de inspeccionar el archivo CSV, pero preferiría no tener que hacerlo (ir a la automatización).

Imagino que tendría que analizar los primeros 3? filas del archivo CSV y busca un patrón de algún tipo para compararlo con los encabezados. Estoy teniendo pesadillas de tres casos particularmente malos en los que:

  1. Las cabeceras incluyen datos numéricos por alguna razón
  2. Las primeras filas (o grandes porciones de la CSV) son nulos
  3. Hay encabezados y datos parecen demasiado similares para distinguirlos

Si puedo obtener una "mejor estimación" y hacer que el analizador falle con un error o escupe una advertencia si no puede decidir, está bien. Si esto es algo que va a ser tremendamente caro en términos de tiempo o computación (y toma más tiempo de lo que se supone que debe salvarme), felizmente desecharé la idea y volveré a trabajar en "cosas importantes".

Estoy trabajando con PHP, pero esto me parece más una cuestión algorítmica/computacional que algo específico de la implementación. Si hay un algoritmo simple que puedo usar, genial. Si puede indicarme alguna teoría/discusión relevante, también sería genial. Si hay una biblioteca gigante que hace procesamiento de lenguaje natural o 300 tipos diferentes de análisis sintáctico, no estoy interesado.

+0

No creo que pueda alcanzar la "fiabilidad" adivinando los encabezados. A menos que sus datos sean bastante consistentes (por ejemplo, son todos los números y es fácil discernir los encabezados y los datos). –

+0

Bueno, cualquier prueba solo tiene que detectar exitosamente un encabezado en una columna, y el resultado puede aplicarse posteriormente a todo el archivo. Si hay un conjunto razonable de criterios que se pueden aplicar a al menos ciertos tipos de datos/columnas, aún puede funcionar la mayor parte del tiempo. – cbednarski

Respuesta

13

Como han señalado otros, no se puede hacer esto con una fiabilidad del 100%. Sin embargo, hay casos en los que es más útil obtener la mayoría de las veces, por ejemplo, las herramientas de hoja de cálculo con la función de importación de CSV a menudo tratan de resolver esto por sí mismas. He aquí algunas heurísticas que tiendan a indicar la primera línea no es un encabezado:

  • La primera fila tiene columnas que no son cadenas o están vacías
  • columnas La primera de las filas no son todos únicos
  • La primera fila parece contener fechas u otros formatos de datos comunes (por ejemplo, xx-xx-xx)
+0

Grandes ideas, Nick. Eso me da algo con lo que trabajar. Gracias. :) – cbednarski

2

En el sentido puramente abstracto, no creo que haya una respuesta algorítmica infalible a su pregunta, ya que se reduce a: "¿Cómo distingo los datos A de los datos B si no sé nada de ninguno de ellos?". Siempre existirá la posibilidad de que dataA sea indistinguible de los datosB. Dicho esto, comenzaría con la complejidad simple y solo agregue según sea necesario. Por ejemplo, si examina las primeras cinco filas, para una columna (o columnas) si el tipo de datos en las filas 2-5 es el mismo pero difiere del tipo de datos en la fila 1, hay una buena probabilidad de que haya una fila de encabezado (el aumento de los tamaños de muestra reduce la posibilidad de error). Esto resolvería (sorta) # 1/# 3 - quizás arroje una excepción si las filas están todas pobladas pero los datos son indistinguibles para permitir que el programa llamante decida qué hacer a continuación. Para el n. ° 2, simplemente no cuente una fila como una fila a menos que y hasta que extraiga datos no nulos ... eso funcionaría en todo menos en un archivo vacío (en cuyo caso presionaría EOF). Nunca sería infalible, pero podría ser "lo suficientemente cerca".

1

Realmente depende de cuán "general" quiere que sea su herramienta. Si los datos serán siempre numéricos, lo tendrá fácil siempre que asuma encabezados no numéricos (lo que parece una suposición bastante justa).

Pero más allá de eso, si usted no sabe ya qué patrones están presentes en los datos, entonces no puede realmente probarlos con anticipación.

FWIW, de hecho acabo de escribir un script para analizar algunas cosas de TSV, todas de la misma fuente. El enfoque de la fuente para los encabezados/formateo estaba tan disperso que tenía sentido simplemente hacer que el guión me hiciera preguntas desde la línea de comandos durante la ejecución. (¿Es esto un encabezado? ¿Qué columnas son importantes?). Entonces no hay automatización, pero me permite revisar los conjuntos de datos en los que estoy trabajando, en lugar de tratar de anticipar cada caso de formato divertido. Además, mis respuestas se guardan en un archivo, por lo que solo tengo que participar una vez por archivo. No es ideal, pero eficiente.

+0

"... hacer que el script me haga preguntas desde la línea de comandos mientras se ejecuta." Tengo algo similar en un formulario web que también acepta CSV, y es eficaz, aunque no glamoroso. Sin embargo, me gusta la idea de almacenar en caché los resultados. Eso podría ser un buen compromiso. – cbednarski

5

En el sentido más general, esto es imposible. Este es un archivo CSV válido:
Nombre
Jim
Tom
Bill

mayoría de los lectores csv se acaba de tomar HasHeader como una opción, y permitirá pasar en su propia cabecera si lo desea. Incluso en el caso que crea que puede detectar, que son encabezados de caracteres y datos numéricos, puede encontrarse con una falla catastrófica. ¿Qué pasa si su columna es una lista de series de BMW?
M

Se procesará esta manera incorrecta. Lo peor de todo es que perderás el mejor auto.

0

Si CSV tiene un encabezado como este.

de identificación, nombre, correo electrónico, fecha 1, John, [email protected] 12 Ene 2020

A continuación, haciendo un filter_var (str, FILTER_VALIDATE_EMAIL) en la fila de encabezado fallará. Dado que la dirección de correo electrónico está solo en los datos de la fila. Por lo tanto, compruebe la fila de encabezado de una dirección de correo electrónico (suponiendo que su archivo CSV tenga direcciones de correo electrónico).

Segunda idea. http://php.net/manual/en/function.is-numeric.php Compruebe la fila de encabezado para is_numeric, lo más probable es que una fila de encabezado no tenga datos numéricos. Pero lo más probable es que una fila de datos tenga datos numéricos.

Si sabe que tiene fechas en sus columnas, también podría funcionar comprobar la fila de encabezado para una fecha.

Obviamente necesita el tipo de datos que espera. Estoy "esperando" direcciones de correo electrónico.

Cuestiones relacionadas