Python / Pandas CSV Parsing

Usé el widget de lista configurable de JotForm para recostackr datos, pero tengo problemas para analizar los datos resultantes correctamente. Cuando yo uso

testdf = pd.read_csv ("TestLoad.csv") 

Los datos se leen como dos registros y los detalles se almacenan en la columna “Información”. Entiendo por qué se analiza de la forma en que está, pero me gustaría dividir los detalles en varios registros como se indica a continuación.

Cualquier ayuda sería apreciada.

Muestra CSV

 "Date","Information","Type" "2015-12-06","First: Tom, Last: Smith, School: MCAA; First: Tammy, Last: Smith, School: MCAA;","New" "2015-12-06","First: Jim, Last: Jones, School: MCAA; First: Jane, Last: Jones, School: MCAA;","New" 

Resultado actual

 Date Information Type 2015-12-06 First: Tom, Last: Smith, School: MCAA; First: Tammy, Last: Smith, School: MCAA; New 2015-12-06 First: Jim, Last: Jones, School: MCAA; First: Jane, Last: Jones, School: MCAA; New 

Resultado deseado

 Date First Last School Type 2015-12-06 Tom Smith MCAA New 2015-12-06 Tammy Smith MCAA New 2015-12-06 Jim Jones MCAA New 2015-12-06 Jane Jones MCAA New 

Este es un texto inútil que se requiere para evitar que los moderadores escriban una respuesta negativa. Aquí están los datos que utilicé:

 "Date","Information","Type" "2015-12-07","First: Jim, Last: Jones, School: MCAA; First: Jane, Last: Jones, School: MCAA;","Old" "2015-12-06","First: Tom, Last: Smith, School: MCAA; First: Tammy, Last: Smith, School: MCAA;","New" 

 import pandas as pd import numpy as np import csv import re import itertools as it import pprint import datetime as dt records = [] #Construct a complete record for each person colon_pairs = r""" (\w+) #Match a 'word' character, one or more times, captured in group 1, followed by.. : #A colon, followed by... \s* #Whitespace, 0 or more times, followed by... (\w+) #A 'word' character, one or more times, captured in group 2. """ colon_pairs_per_person = 3 with open("csv1.csv", encoding='utf-8') as f: next(f) #skip header line record = {} for date, info, the_type in csv.reader(f): info_parser = re.finditer(colon_pairs, info, flags=re.X) for i, match_obj in enumerate(info_parser): key, val = match_obj.groups() record[key] = val if (i+1) % colon_pairs_per_person == 0: #then done with info for a person record['Date'] = dt.datetime.strptime(date, '%Y-%m-%d') #So that you can sort the DataFrame rows by date. record['Type'] = the_type records.append(record) record = {} pprint.pprint(records) df = pd.DataFrame( sorted(records, key=lambda record: record['Date']) ) print(df) df.set_index('Date', inplace=True) print(df) --output:-- [{'Date': datetime.datetime(2015, 12, 7, 0, 0), 'First': 'Jim', 'Last': 'Jones', 'School': 'MCAA', 'Type': 'Old'}, {'Date': datetime.datetime(2015, 12, 7, 0, 0), 'First': 'Jane', 'Last': 'Jones', 'School': 'MCAA', 'Type': 'Old'}, {'Date': datetime.datetime(2015, 12, 6, 0, 0), 'First': 'Tom', 'Last': 'Smith', 'School': 'MCAA', 'Type': 'New'}, {'Date': datetime.datetime(2015, 12, 6, 0, 0), 'First': 'Tammy', 'Last': 'Smith', 'School': 'MCAA', 'Type': 'New'}] Date First Last School Type 0 2015-12-06 Tom Smith MCAA New 1 2015-12-06 Tammy Smith MCAA New 2 2015-12-07 Jim Jones MCAA Old 3 2015-12-07 Jane Jones MCAA Old First Last School Type Date 2015-12-06 Tom Smith MCAA New 2015-12-06 Tammy Smith MCAA New 2015-12-07 Jim Jones MCAA Old 2015-12-07 Jane Jones MCAA Old 

Utilicé separadores de expresiones regulares con el motor de Python para poder especificar varios separadores. Luego, utilicé el parámetro usecols para especificar qué columnas del archivo csv desea en su dataframe. El encabezado no se leerá desde el archivo y salté la primera fila ya que no tiene ningún dato. Leí el primer y el segundo conjunto de registros en 2 marcos de datos, y luego concatené los 2 marcos de datos.

 a = pd.read_csv('sample.csv', sep=',|:|;', skiprows = 1, usecols = (0,2,4,6, 14), header = None, engine='python') b = pd.read_csv('sample.csv', sep=',|:|;', skiprows = 1, usecols = (0,8,10,12,14), header = None, engine='python') a.columns = ['Date', 'First', "Last", 'School', 'Type'] b.columns = ['Date', 'First', "Last", 'School', 'Type'] final_data = pd.concat([a,b], axis = 0) 

Si necesita conservar el orden, de modo que los segundos nombres aparezcan justo debajo del nombre, puede ordenarlos utilizando los índices. Utilizo mergesort, porque es una clasificación estable y esto garantiza que el primer registro de información (el registro de la derecha) estará por encima del registro de información de la izquierda.

 final_data.sort_index(kind='mergesort', inplace = True) >>>final_data Date First Last School Type 0 "2015-12-06" Tom Smith MCAA "New" 0 "2015-12-06" Tammy Smith MCAA "New" 1 "2015-12-06" Jim Jones MCAA "New" 1 "2015-12-06" Jane Jones MCAA "New" 

Edición: Incluyendo el segundo conjunto del registro en los datos. Se cambió el eje a 0.