Группировать без использования pandas - PullRequest
0 голосов
/ 20 апреля 2020

У меня есть 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

Ответы [ 2 ]

1 голос
/ 20 апреля 2020

Вы можете использовать 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 для этой проблемы, но лично я не нахожу это ни естественным, ни очень Pythoni c. Но вот как это делается в любом случае.

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 по какой-то причине, я бы порекомендовал go с ответом Amal TS ', чтобы построить словарь в al oop вместо.

1 голос
/ 20 апреля 2020

Есть несколько способов сделать это. Использование дерева или простого dict.

В этом решении предполагается, что поля в группе по смежны. С небольшими изменениями вы можете обобщить или исследовать древовидный подход для аккуратного решения.

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')```
...