2015-09-04 101 views
0

我有一個CSV文件中的數據集。下面是一個示例:如何在Python中彙總CSV文件中的列值

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是與ID的狀態符號,以便每個狀態可以具有與每companyid不同的ID的多個行。我想要做的是,對於每個companyid我想爲特定的time特定狀態添加所有amount。例如在上面的示例中,companyid 1有兩個time2012Q1的記錄 - 一個用於AK_995,另一個用於AK_996。我想在這兩項中添加金額,並且只需要AK作爲location,即可獲得一個值爲2012Q1,AK,1,13484260.129的記錄。這應該爲每個companytime期間爲所有州完成。請注意,不應該如time那樣添加,如上面的樣本companyid3有2個記錄爲相同的狀態,但在不同的time期間。此外,我只想在MetricsSales的情況下執行此操作,因此我想刪除Metrics不是Sales的任何行,也不要在聚合中添加這些數量。

我也想寫輸出到另一個csv文件。我怎樣才能做到這一點?

更新部分:

按照建議的@MichaelLaszlo我有這樣的代碼。代碼似乎有一個問題。我想在輸出文件中將特定的companyid的所有記錄放在一起。 companyid內的記錄順序應該是按照明智的time遞增的順序(針對特定位置的記錄聚集在一起用於特定的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) 

運行上面的腳本和檢查結果文件aggregated.csv

+0

會有很大幫助我遇到了一個輸出即將到來的問題。我已將我的問題發佈在上述文章的更新部分中。我想要的是讓一家公司的所有記錄在一起,並且在每家公司內,特定州的記錄應該在一起並按季度訂購 – user2966197

+0

我已修改我的代碼以合併您描述的更改。它需要改變兩行:'key =(row [2],row [1] [:2],row [0])'和key,sort中的值(totals.items()):'無論如何,我建議您複製並粘貼修改後的答案中的整個腳本。 –

+0

謝謝!你能幫我解釋'key'(尤其是'row [1] [:2]')是如何形成的嗎? – user2966197

2

我不知道你的數據集的大小,但你應該開始考慮使用熊貓。 您將受益於許多工具,如從csv到按列分組創建數據框。最後,您可以靈活地選擇輸出,而且速度非常快。

編輯: 對不起,我只有我的手機,但現在這裏是一個CSV如何,並生成一個數據幀: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() 

然後您可以使用Dataframe中的to_csv()函數導出數據。

更新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

不知道,閹這是你在找什麼,但你可以例如使用一個字典,收集您感興趣的項下的值,有點像這樣:

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

編輯:空行

開始的添加操作通過讀取數據到大熊貓數據幀:

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' 
)