2013-07-18 3 views
0

У меня есть данные в csv, которые необходимо разобрать. Это выглядит следующим образом:Python CSV - необходимо суммировать значения в столбце, сгруппированном по значению в другом столбце

Date, Name, Subject, SId, Mark 
2/2/2013, Andy Cole, History, 216351, 98 
2/2/2013, Andy Cole, Maths, 216351, 87 
2/2/2013, Andy Cole, Science, 217387, 21 
2/2/2013, Bryan Carr, Maths, 216757, 89 
2/2/2013, Carl Jon, Botany, 218382, 78 
2/2/2013, Bryan Carr, Biology, 216757, 27 

мне нужно иметь Sid как ключ и суммировать все значения в столбце меток с помощью этого ключа. выход будет что-то вроде:

Sid  Mark 
216351 185 
217387 21 
216757 116 
218382 78 

Я не должен писать вывод на файл. Мне просто понадобится, когда я запустил файл python. Это аналогичный question. Как это изменить, чтобы пропускать столбцы между ними?

+0

Я не понимаю использования подчеркивания в первом ответе. Я попытался использовать тот же код с таким количеством символов подчеркивания для всех столбцов, которые я хочу игнорировать. –

+1

Использование подчеркивания как переменной просто означает «Мне не нужна эта переменная». Вы можете использовать фактические имена, такие как 'Date, Name, Subject, SId, Mark = row', если хотите, а затем просто не ссылайтесь на имена, если это поможет вам понять. – abarnert

ответ

2

Это понятие гистограммы. Используйте defaultdict(int) от collections и итерации по строкам. Используйте значение «Sid» в качестве ключа для dict и добавьте значение «Mark» к текущему значению.

defaultdict типа междунар убеждается, что если ключ не существует до сих пор его значение становится инициализируется 0.

from collections import defaultdict 

d = defaultdict(int) 

with open("data.txt") as f: 
    for line in f: 
     tokens = [t.strip() for t in line.split(",")] 
     try: 
      sid = int(tokens[3]) 
      mark = int(tokens[4]) 
     except ValueError: 
      continue 
     d[sid] += mark 

print d 

Выход:

defaultdict(<type 'int'>, {217387: 21, 216757: 116, 218382: 78, 216351: 185}) 

Вы можете изменить парсинга часть в что-нибудь еще (например, используйте csvreader или выполните другие проверки). Ключевым моментом здесь является использование defaultdict(int) и обновить его следующим образом:

d[sid] += mark 
0

Если вы хотите адаптировать решение по указанной ссылке, вы можете изменить, какие строки распаковывать.

Вот идея (адаптировано из раствора samplebias'S в ссылке OP в):

import csv 
from collections import defaultdict 

# a dictionary whose value defaults to a list. 
data = defaultdict(list) 
# open the csv file and iterate over its rows. the enumerate() 
# function gives us an incrementing row number 
for i, row in enumerate(csv.reader(open('data.csv', 'rb'))): 
    # skip the header line and any empty rows 
    # we take advantage of the first row being indexed at 0 
    # i=0 which evaluates as false, as does an empty row 
    if not i or not row: 
     continue 
    # unpack the columns into local variables 


    _, _, _, SID, mark = row#### <--- HERE, change what you unpack 


    # for each SID, add the mark the list 
    data[SID].append(float(mark)) 

# loop over each SID and its list of mark and calculate the sum 
for zipcode, mark in data.iteritems(): 
    print SID, sum(mark) 
+0

Он выдает сообщение об ошибке: Слишком много значений для распаковки. –

+0

Это было бы проще с 'DictReader'.Тогда вам не нужно пропускать заголовок, и вы можете просто сделать SID, mark = row ['SId'], row ['Mark'] 'вместо того, чтобы объяснять, как пропускать столбцы. – abarnert

+0

ОП задал вопрос: «Как это изменить, чтобы пропускать столбцы между ними?» – jh314

-1

Во-первых, для разбора CSV, используйте csv модуль:

with open('data.csv', 'rb') as f: 
    data = csv.DictReader(f) 

Теперь вы хотите сгруппировать их Сидом. Вы можете сделать это, сортируя, затем используя groupby. (Сортировка не требуется, если одинаковые значения всегда будут непрерывными.)

siddata = sorted(data, key=operator.itemgetter('SId')) 
    sidgroups = itertools.groupby(siddata, operator.itemgetter('SId')) 

Теперь вы хотите, чтобы суммировать значения в каждой группе:

for key, group in sidgroups: 
     print('{}\t{}'.format(key, sum(int(value['Mark']) for value in group)) 

В качестве альтернативы, вы можете просто написать все в базу данных и дайте SQLite выяснить, как это сделать для вас:

with open('data.csv', 'rb') as f, sqlite3.connect(':memory:') as db: 
    db.execute('CREATE TABLE data (SId, Mark)') 
    db.executemany('INSERT INTO data VALUES (:SId, :Mark)', csv.DictReader(f)) 
    cursor = db.execute('SELECT SId, SUM(Mark) AS Mark FROM data GROUP BY SId') 
    for row in cursor: 
     print('{}\t{}'.format(row)) 
Смежные вопросы

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