2015-12-08 10 views
0

Я использовал JotForm Настраиваемый виджет списка для сбора данных, но с ошибками корректно анализировал результирующие данные. Когда я используюPython/Pandas CSV Parsing

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

Данные считываются как две записи, а данные хранятся в столбце «Информация». Я понимаю, почему он разбирается так, как есть, но я хотел бы разбить детали на несколько записей, как указано ниже.

Любая помощь будет оценена по достоинству.

Образец 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" 

Текущий результат

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 

Желаемая Result

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 

ответ

2

Это бесполезный текст, который необходим для того, чтобы сохранить ответ от замещения модераторами. Вот данные, которые я использовал:

"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 
+0

7stud - спасибо за решение. Это метод подхода, который я использовал, поскольку число людей в записи может быть 1: n – Zymurgist66

0

Я использовал регулярные выражения сен араторы с движком python, чтобы я мог указать несколько разделителей. Затем я использовал параметр usecols, чтобы указать, какие столбцы в файле csv вам нужны в вашем фреймворке данных. Заголовок не будет считан из файла, и я пропустил первую строку, так как у нее нет данных. Я прочитал в первом и втором наборах записей на 2 кадрах данных, а затем объединил 2 кадра данных.

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) 

Если вам нужен порядок сохраняется, таким образом, что вторые имена появляются прямо под первым именем, вы можете сортировать с помощью индексов. Я использую mergesort, потому что он является стабильным, и это гарантирует, что первая информационная запись (запись справа) будет выше Информационной записи слева.

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" 

Редактировать: Включая второй набор записей в данные. Изменена ось до 0.

+0

Спасибо за подход. Я смог реплицировать, однако, когда я попробовал это, код не взял второе имя в каждой из строк (например, Тамми Смит и Джейн Джонс). Есть ли что-то, что мне нужно сделать по-другому, чтобы перебирать текст в столбце «Информация»? – Zymurgist66

+0

@ Zymurgist66 Должны ли записи появляться так, что Том Смит должен появиться прямо над Тимми Смитом? В любом случае, я отредактировал свой ответ, чтобы прочитать оба набора имен, и предоставил опцию, чтобы заказ можно было сохранить. – imp9

+0

пользователь1435522 - нет необходимости. Первоначальные примеры, которые я тестировал, имели только 2 человека за запись. Когда я попытался использовать весь набор данных, я обнаружил, что число людей может быть 1: n, поэтому мне пришлось перебирать людей. – Zymurgist66

Смежные вопросы