python - 不使用 pandas 分组
问题描述
我有一个 csv 文件,样本看起来像,
year product country
2018 food us
2018 drink uk
2019 food uk
2019 car japan
2018 food japan
我可以在不使用 pandas 或 numpy 等软件包的情况下按年份对信息进行分组吗?我知道我们可以先使用标准包读取输入csv
。
f = open('text.csv')
csv_f = csv.reader(f)
for row in csv_f:
////////
我的预期输出是,
year product product_sum
2018 food 2
2018 drink 1
2019 food 1
2019 car 1
解决方案
您可以使用collections.Counter
来计算出现次数。
f = open('text.csv')
csv_f = csv.reader(f)
next(csv_f, None) # Ignore header row
c = collections.Counter((year, product) for year, product, country in csv_f)
print(c)
# Output: Counter({('2018', 'food'): 2, ('2018', 'drink'): 1, ('2019', 'food'): 1, ('2019', 'car'): 1})
要将其写回 CSV 文件,您可以使用.items()
和列表推导将其转换回平面列表并使用writerows
.
with open('output.csv', 'w') as csvfile:
writer = csv.writer(csvfile)
writer.writerow(('year', 'product', 'product_sum'))
writer.writerows([(key[0], key[1], value) for key, value in c.items()])
注意:对于 Python 2,使用iteritems()
而不是items()
.
你可以使用reduce
这个问题,但我个人觉得这不是很自然也不是很 Pythonic。但无论如何,这就是它的完成方式。
def reduce_func(acc, update):
year, product, country = update
acc[(year, product)] += 1
return acc
resultdict = reduce(reduce_func,
csv_f,
collections.defaultdict(lambda: 0))
print(resultdict)
# Output: defaultdict(<function <lambda> at 0x1007042f0>, {('2018', 'food'): 2, ('2018', 'drink'): 1, ('2019', 'food'): 1, ('2019', 'car'): 1})
如果您出于某种原因不想/不能使用collections.Counter
,我建议您使用 Amal TS 的答案来循环构建字典。
推荐阅读
- postgresql - 如果选择查询返回行,如何引发错误
- ssis - 在 SSIS 中使用 OLE DB 从 Sybase 提取数据时出错
- unity3d - unity Vector3.Dot 返回值错误
- python - AWS Elastic Beanstalk 504 网关超时期间会发生什么
- c# - 在构造函数中注册具有额外值参数的装饰器
- three.js - threejs/raycaster 将看不到我需要的对象
- javascript - 在页面中多次重用 jQuery 的 getJSON
- javascript - 滚动行为 VueJS 无法正常工作
- python - 用python读取文件json
- java - System.console() 为空