2015-09-04 3 views
0

У меня есть набор данных в CSV-файле. Вот пример:Как суммировать значения столбцов из файла CSV в Python

Time,Location,Companyid,Metrics,Amount 

2012Q1,AK_995,A,Sales,8820156.363 
2012Q1,AK_995,B,Revenue,28392730.51 
2012Q1,AK_995,C,Sales,6980332.166 
2012Q1,AK_996,B,Revenue,1894254.13 
2012Q1,AK_996,A,Sales,4664103.766 
2012Q2,AK_995,C,Sales,7980332.166 

Здесь time в год и квартал, location это состояние символ с идентификатором, чтобы каждое состояние может иметь несколько строк с различными идентификаторами в companyid. Что я хочу сделать, так это то, что для каждого companyid я хочу добавить все amount для конкретного штата по конкретному time. Например, в приведенном выше образце companyid 1 имеет две записи для time2012Q1 - один для AK_995 и один для AK_996. Я хочу добавить сумму в эти два и просто AK как location, чтобы получить одну запись со значениями 2012Q1,AK,1,13484260.129. Это должно быть сделано для каждого company за time период для всех состояний. Обратите внимание, что amounts через time не следует добавлять, как в приведенном выше образце. companyid3 был 2 записей для этого штата, но в другом time период. Также я хочу сделать это только там, где Metrics - Sales, поэтому я хочу удалить любую строку, где Metrics отличен от Sales, и не добавляйте эту сумму в агрегирование.

Я также хочу записать вывод в другой файл csv. Как я могу это сделать?

UPDATE РАЗДЕЛ:

По предложению @MichaelLaszlo У меня есть этот код. Кажется, что у кода есть одна проблема. В выходном файле я хочу, чтобы все записи для конкретного companyid собрались вместе. Порядок записей в пределах companyid должен быть в порядке возрастания time за location мудрый (записи для определенного места объединяются для конкретного companyid). Так, например, если есть companyidB тогда все записи companyidB должны быть вместе, и там порядок должен быть, как показано ниже:

companyid,state,time,amount 
B,AK,2010Q1,5000 
B,AK,2010Q2,5100 
B,AK,2010Q3,4300 
B,AK,2010Q4,4350 
B,AK,2011Q1,5600 

Как вы можете видеть выше всех записей companyidB вместе и в companyidB Записи для конкретного location находятся в очереди time. В моем текущем выпуске я получаю записи для всех companyids разбросанных. Мой текущий код:

totals = {} 

# Aggregate sales by quarter, state, and company. 
for row in csv.reader(open('data.csv')): 
    if row[3] == 'Sales': 
    key = (row[0], row[1][:2], row[2]) 
    totals[key] = totals.setdefault(key, 0) + float(row[4]) 

# Write aggregated data to file. 
with open('aggregated.csv', 'w') as out_file: 
    writer = csv.writer(out_file) 
    for key, value in totals.items(): 
    row = list(key) + [value] 
    writer.writerow(row) 

Мой выходной ток образца:

time,state,companyid,amount 
2014Q4,AL_,B,547991592.5101689 
2014Q1,NV_,B,387534045.40654004 
2012Q3,SC_,A,333657617.05835015 
2014Q4,DC_,C,54022786.60577 
2014Q3,TN_,B,594121931.7221502 

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

+0

Что именно ваша проблема? Чтение csv может быть выполнено, как описано в: https://docs.python.org/2/library/csv.html – haraldkl

+0

@haraldkl. Моя проблема в том, что я не знаю, как выполнить агрегирование, описанное в моем сообщении выше. Я знаю, как читать файл csv, но его обработка беспокоит меня, поскольку я новичок в этом. – user2966197

ответ

3

агрегирования данных, использовать хэш. Сделайте ключи из кортежей значений, которые вы хотите скопировать.

totals = {} 

for row in csv.reader(open('data.csv')): 
    if row[3] == 'Sales': 
    key = (row[2], row[1][:2], row[0]) 
    totals[key] = totals.setdefault(key, 0) + float(row[4]) 

Для записи в файл CSV, используйте csv.writer() на открытом объекте файла. Чтобы создавать строки, конвертируйте каждый хэш-ключ в список и объедините его с общим объемом продаж.

import csv 

with open('aggregated.csv', 'w') as out_file: 
    writer = csv.writer(out_file) 
    for key, value in sorted(totals.items()): 
    row = list(key) + [value] 
    writer.writerow(row) 

Мы можем поставить эти две операции вместе в короткий сценарий:

import csv 

totals = {} 

# Aggregate sales by company, state, and quarter. 
for row in csv.reader(open('data.csv')): 
    if row[3] == 'Sales': 
    key = (row[2], row[1][:2], row[0]) 
    totals[key] = totals.setdefault(key, 0) + float(row[4]) 

# Write aggregated data to file. 
with open('aggregated.csv', 'w') as out_file: 
    writer = csv.writer(out_file) 
    for key, value in sorted(totals.items()): 
    row = list(key) + [value] 
    writer.writerow(row) 

Run выше сценарий и проверьте полученный файл aggregated.csv.

+0

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

+0

Я пересмотрел свой код, чтобы включить описанные вами изменения , Это потребовало изменения двух строк: 'key = (строка [2], строка [1] [: 2], строка [0])' и 'для ключа, значение в sorted (totals.items()):' Во всяком случае, я предположим, что вы копируете и вставляете весь сценарий из моего пересмотренного ответа. –

+0

спасибо! Можете ли вы помочь мне объяснить, как именно формируется «ключ» (особенно «строка [1] [: 2]»)? – user2966197

2

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

Edit: К сожалению у меня только мой телефон сейчас, но вот как из CSV и создать Dataframe: http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.from_csv.html А вот GroupBy: http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.groupby.html Это будет выглядеть так:

import pandas as pd 

df = pd.DataFrame.from_csv(r'yourPathToCsv.csv') 

data_grouped = df.groupby(['col1','col2'])['colAmount'].sum().to_frame() 

Тогда вы можете экспортировать данные с помощью функции to_csv() из Dataframe.

Обновление: метод read_csv теперь предпочтителен методу from_csv. Вот обновленный пример:

import pandas as pd 

df = pd.read_csv(r'yourPathToCsv.csv') 

data_grouped = df.groupby(['col1','col2'])['colAmount'].sum().to_frame() 
+0

Я добавлю образец для вас – Alex

+0

пример для данных примера, которые я опубликовал выше, будет очень полезен для понимания. – user2966197

0

Не уверен, погода это то, что вы ищете, но вы могли бы, например, использовать Dict, чтобы собрать значения под ключ вы заинтересованы, то вроде этого:

agg = {} 

for row in dat: 
    if row[3] == 'Sales': 
    state = row[1][:1] 
    old = agg.get((row[0], state, row[2]), 0.0) 
    agg[(row[0],state,row[2])] = old + row[4] 

где dat хранит данные из таблицы csv.

1

Простой, но не является оптимальным для больших объемов данных:

import csv 

source = {} 
with open('filename.csv', 'rb') as csvfile: 
    csvreader = csv.reader(csvfile, delimiter=',', quotechar='"') 
    next(csvreader , None) # skip line 
    next(csvreader , None) # skip line 
    for row in csvreader: 
     if row[3] != 'Sales': 
      continue 
     data_date = row[0] 
     data_state = row[1].split('_')[0] 
     data_company = row[2] 
     data_amount = float(row[4]) 
     if data_date not in source: 
      source[data_date] = {} 
     if data_state not in source[data_date]: 
      source[data_date][data_state] = {} 
     if data_company not in source[data_date][data_state]: 
      source[data_date][data_state][data_company] = [] 
     source[data_date][data_state][data_company].append(data_amount) 

    for k_date in source: 
     for k_state in source[k_date]: 
      for k_company in source[k_date][k_state]: 
       data = source[k_date][k_state][k_company] 
       average = (sum(data)/len(data)) 
       print('%s,%s,%s,%s' % (k_date, k_state, k_company, average)) 
0

EDIT: Добавлена ​​обработка пустой строки

Начните с чтения данных на панд dataframe:

import pandas as pd 
data = pd.read_csv('data.csv') 

Удалить пустую строку:

data.dropna(how="all", inplace=True) 

Переименовать столбец местоположение:

data['Location'] = data['Location'].apply(
    lambda location: location.split('_')[0] 
) 

Затем выполните обработку и сохранить в файл:

data[data['Metrics']=='Sales'].groupby(
    ['Time','Location','Companyid'] 
).sum().to_csv(
    'results.csv' 
) 
Смежные вопросы