php - google - Detección automática de la presencia de encabezados CSV en un archivo
formato de encabezados y eventos en archivos csv (5)
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".
Pregunta breve: ¿Cómo puedo detectar automáticamente si un archivo CSV tiene encabezados en la primera fila?
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).
Me 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. Tengo pesadillas de tres casos particularmente malos en los que:
- Los encabezados incluyen datos numéricos por alguna razón
- Las primeras pocas filas (o grandes porciones del CSV) son nulas
- Los encabezados y los datos parecen muy similares para distinguirlos
Si puedo obtener una "mejor estimación" y hacer que el analizador falle con un error o escupir 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.
Realmente depende de qué tan "general" quieras que sea tu herramienta. Si los datos serán siempre numéricos, lo tendrá fácil siempre y cuando asuma encabezados no numéricos (lo que parece bastante suposición razonable).
Pero más allá de eso, si aún no sabe 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.
Como han señalado otros, no 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. Aquí hay algunas heurísticas que tienden a indicar que la primera línea no es un encabezado:
- La primera fila tiene columnas que no son cadenas o están vacías
- Las columnas de la primera fila no son todas únicas
- La primera fila parece contener fechas u otros formatos de datos comunes (p. Ej., Xx-xx-xx)
En el sentido más general, esto es imposible. Este es un archivo csv válido:
Nombre
Jim
Tom
Cuenta
La mayoría de lectores csv solo tomarán hasHeader como una opción, y le permitirán pasar su propio encabezado 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?
METRO
3
5
7
Procesarás esto incorrectamente. Lo peor de todo es que perderás el mejor auto.
Si tu CSV tiene un encabezado como este.
ID, nombre, correo electrónico, fecha 1, john, [email protected], 12 de enero de 2020
Luego, hacer un filter_var (str, FILTER_VALIDATE_EMAIL) en la fila del 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 del encabezado para una fecha.
Obviamente, necesitas qué tipo de datos estás esperando. Estoy "esperando" direcciones de correo electrónico.