我对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()
答案 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