2015-09-04 102 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' 
)