求和 csv 文件中未排序的列列表?
Sum an unsorted list of columns in csv file?
我是 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个"Items"(重复,但顺序不同,有时只出现一次或两次),每个都有一个"current value"(整数,从0到大约 10 亿(或 1 billion/milliard),当前百分比值(目前我不感兴趣),以及与上次读数相比的百分比变化(不同的文件,目前我不感兴趣)。
我想要实现的是每个 Item
的“change_pct
”列的总和,因此对于上述示例结果将是:
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()
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')
需要注意的几个问题:如果列名中有白色 space,则需要清理它,或者在上面的代码中使用确切的列名(例如 ' name '
而不是 'name'
).
使用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})
一个pandas有效的解决方案:
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)
这是一种相当易读的方法,可以将读取的每一行转换为 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
我是 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个"Items"(重复,但顺序不同,有时只出现一次或两次),每个都有一个"current value"(整数,从0到大约 10 亿(或 1 billion/milliard),当前百分比值(目前我不感兴趣),以及与上次读数相比的百分比变化(不同的文件,目前我不感兴趣)。
我想要实现的是每个 Item
的“change_pct
”列的总和,因此对于上述示例结果将是:
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()
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')
需要注意的几个问题:如果列名中有白色 space,则需要清理它,或者在上面的代码中使用确切的列名(例如 ' name '
而不是 'name'
).
使用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})
一个pandas有效的解决方案:
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)
这是一种相当易读的方法,可以将读取的每一行转换为 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