不使用 pandas 分组

Group by without using 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

有多种方法可以做到这一点。使用树或简单的字典。

此解决方案假定分组依据中的字段是相邻的。只需稍作更改,您就可以概括或探索基于树的方法以获得简洁的解决方案。

f = open('text.csv')
delim = "\t"
header = f.readline()
group_dict = {}
for l in f.readlines():
      key = delim.join(l.split()[:2])
      if key not in group_dict:
            group_dict[key] = 0
      group_dict[key] +=1

f2 = open('output.txt','w')
f2.write(header)
for k,v in group_dict.items():
      f2.write(delim.join([k,str(v)])+'\n')```

您可以使用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()])

注:对于Python2,使用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 的答案来循环构建字典。