在csv文件中汇总未排序的列列表?

时间:2017-01-17 21:56:40

标签: python csv columnsorting

我对Python非常陌生(在脚本编写方面非常生疏,我的最后一次试验是bash和Perl在2001年左右),已经尝试过搜索SO - 但老实说甚至不知道该找什么。我很确定这是微不足道的 - 我有点惭愧。

我有一个相当大的CSV文件(约26k行),采用制表符分隔格式:

name, current_value, current_pct, change_pct
ItemA 2452434324     7,70%        -1,19
ItemB 342331         2,40%        -0,45
ItemC 32412123       3,90%        3,87
ItemD 0              0            -4,52
ItemE 12318231       14,80%       0
ItemA 542312134      1,60%        0,11
ItemC 2423423425     11,21%       -0,01
ItemE 3141888103     30,00%       0
ItemB 78826          1,01%        12,01
ItemA 89937          0,04%        0
...

总共大约300个“项目”(重复,但按各种顺序,有时只出现一次或两次),每个都有一个“当前值”(整数,从0到大约1000万(或10亿/毫安)),当前百分比值(此刻对我不感兴趣),以及上次阅读的百分比变化(不同文件,此刻对我来说不感兴趣)。 我想要实现的是每个change_pct的“Item”列的总和,因此对于上述示例结果将是:

name    total_pct_change
ItemA   -1,08
ItemB   11,56
ItemC   3,86
ItemD   -4,52
ItemE   0

我打算创建一个items列表,然后只为这些值加row[3]的值,但我失败了。 我到现在所拥有的:

import csv, sys, string
xlsfile = sys.argv[1]
with open(xlsfile, 'rb') as f:
    reader = csv.reader(f, delimiter='\t')
    item = row[0]
    pct_change = row[3]
    # this is where I draw a blank
    # was thinking of something akin to
    #   foreach item do sum(pct_change)
    # but that's obviously wrong
    print item, sum_pct_change
f.close()

4 个答案:

答案 0 :(得分:1)

Pandas是处理表格数据的绝佳工具。

在这里,您可以:

import pandas as pd

data = pd.read_csv('path_to_your_file', sep='\t', header=0, decimal=',')

summed = data.groupby(by=['name'])['change_pct'].sum()

summed.to_csv('name_of_output_file', sep='\t')

需要注意的一些问题是:如果列名中有空格,则需要清理它,或者使用上面代码中的确切列名(例如' name '而不是'name')。

答案 1 :(得分:1)

有效的熊猫解决方案:

import pandas as pd

with open(xlsfile) as fobj:
    header = [entry.strip() for entry in next(fobj).split(',')]

data = pd.read_csv(xlsfile, delim_whitespace=True, decimal=',', names=header, skiprows=1)
summed = data.groupby(by=['name'])['change_pct'].sum()

print(summed)

输出:

name
ItemA    -1.08
ItemB    11.56
ItemC     3.86
ItemD    -4.52
ItemE     0.00
Name: change_pct, dtype: float64

修改

如果您的文件是; - 已分开。这应该有效:

data = pd.read_csv('pct2.csv', sep=';', decimal=',')
summed = data.groupby(by=['name'])['change_pct'].sum()
print(summed)

答案 2 :(得分:0)

使用defaultdict

from collections import defaultdict

with open(xlsfile) as fobj:
    next(fobj)   # throw away first line
    res = defaultdict(float)
    for line in fobj:
        values = line.split()  #  split at whitespace
        #  use value of first column as key
        #  take value of last column  replace `,` by `.` and convert to `float`
        #  and use as value
        res[values[0]] += float(values[-1].replace(',', '.'))

print(res)

输出:

defaultdict(float,
            {'ItemA': -1.0799999999999998,
             'ItemB': 11.56,
             'ItemC': 3.8600000000000003,
             'ItemD': -4.52,
             'ItemE': 0.0})

答案 3 :(得分:0)

这是一种相当可读的方法,可将每行读取转换为namedtuple以简化字段访问:

from collections import namedtuple
import csv
import sys

xlsfile = sys.argv[1]

# define field names for easy access
Record = namedtuple('Record', 'name, current_value, current_pct, change_pct')

totals = {}  # dictionary to hold totals

with open(xlsfile, 'rb') as f:
    reader = csv.reader(f, delimiter='\t')
    next(reader)  # skip over header row
    for rec in (Record._make(row) for row in reader):
        totals[rec.name] = (totals.get(rec.name, 0.0) + float(rec.change_pct))

print('name      total_change_pct')
for item in sorted(totals.items()):
    print('{:5}     {:.2f}'.format(item[0], item[1]))

输出:

name      total_change_pct
ItemA     -1.08
ItemB     11.56
ItemC     3.86
ItemD     -4.52
ItemE     0.00