Учитывая большой массив кортежей, как сгруппировать первый элемент каждого кортежа, чтобы суммировать последний элемент каждого кортежа без фрейма данных Pandas?

У меня есть большой список кортежей, где каждый кортеж содержит 9 строковых элементов:

      pdf_results = [
("Kohl's - Dallas", '-', "Kohl's Cafe", '03/18/22', 'RC', '8', '0', '16', '8'),
("Kohl's - Dallas", '-', "Kohl's Cafe", '03/18/22', 'SMI', '5', '0', '10', '5'),
("Kohl's - Dallas", '-', "Kohl's Cafe", '03/19/22', 'RC', '8', '0', '16', '8'),
("Kohl's - Dallas", '-', "Kohl's Cafe", '03/19/22', 'SMI', '5', '0', '10', '5'),
("Kohl's - Dallas", '-', "Kohl's Cafe", '03/20/22', 'RC', '8', '0', '16', '8'),
("Kohl's - Dallas", '-', "Kohl's Cafe", '03/20/22', 'SMI', '5', '0', '10', '5'),
("Kohl's - Dallas", '-', "Kohl's Cafe", '03/21/22', 'RC', '8', '0', '16', '8'),
("Kohl's - Dallas", '-', "Kohl's Cafe", '03/21/22', 'SMI', '5', '0', '10', '5'),
("Kohl's - Dallas", '-', "Kohl's Cafe", '03/23/22', 'SMI', '5', '0', '10', '5'),
("Kohl's - Dallas", '-', "Kohl's Cafe", '03/24/22', 'RC', '8', '0', '16', '8'),
("Kohl's - Dallas", '-', "Kohl's Cafe", '03/24/22', 'SMI', '5', '0', '10', '5'),
('Bronx-Lebanon Hospital Center', '-', 'Patient Trayline ', '03/18/22', 'RC', '8', '0', '16', '8'),
('Bronx-Lebanon Hospital Center', '-', 'Patient Trayline ', '03/18/22', 'SMI', '5', '0', '10', '5'),
('Bronx-Lebanon Hospital Center', '-', 'Patient Trayline ', '03/19/22', 'RC', '8', '0', '16', '8'),
('Bronx-Lebanon Hospital Center', '-', 'Patient Trayline ', '03/19/22', 'SMI', '5', '0', '10', '5')
]

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

      desired_output = [
("Kohl's - Dallas", 70),
("Bronx-Lebanon Hospital Center", 26)
]

я пытался использовать itertools.groupbyчто кажется наиболее подходящим решением; тем не менее, застряв на правильной итерации, индексации и суммировании последнего элемента каждого кортежа, не сталкиваясь с одним из следующих препятствий:

  1. Последний элемент каждого кортежа имеет тип stringи при преобразовании в intпредотвращает итерацию как TypeError: 'int' object not iterable
  2. ValueErrorподнимается, где invalid literal for int() with base 10: 'b'

Пытаться:

      from itertools import groupby

def getSiteName(siteChunk):
    return siteChunk[0]

siteNameGroup = groupby(pdf_results, getSiteName)

for key, group in siteNameGroup:
    print(key) # 1st element of tuple as desired
    for pdf_results in group:
        # Raises TypeError: unsupported operand type(s) for +: 'int' and 'str'
        print(sum(pdf_results[8]))
    print()

4 ответа

Предполагая, что ваш список отсортирован по первому элементу, вы можете сделать:

      from itertools import groupby 

for k,v in groupby(pdf_results, key=lambda t: t[0]):
    print(k, sum(int(x[-1]) for x in v))

Отпечатки:

      Kohl's - Dallas 70
Bronx-Lebanon Hospital Center 26

Если заказ не отсортирован, просто используйте dictчтобы суммировать элементы, указанные первой записью кортежа:

      res={}

for t in pdf_results:
    res[t[0]]=res.get(t[0],0)+int(t[-1])

>>> res
{"Kohl's - Dallas": 70, 'Bronx-Lebanon Hospital Center': 26}

Ты почти там. Просто измени свой

      for pdf_results in group:
    print(sum(pdf_results[8]))

к:

      print(sum(int(pdf_results[8])
          for pdf_results in group))

(Хотя я бы также переименовал в pdf_result, единственное число.)

Это также будет работать:

      from collections import defaultdict

output = defaultdict(int)

for item in pdf_results:
    output[item[0]] += int(item[-1])

print(list(output.items()))

Выход

      [("Kohl's - Dallas", 70), ('Bronx-Lebanon Hospital Center', 26)]

Почему бы не использовать простой forзацикливаться на пустом словаре?

      resultDict = {}
for value in pdf_results:
  if value[0] not in resultDict:
    resultDict[value[0]] = 0
  resultDict[value[0]] += float(value[len(value)-1])
print(resultDict)

Выход

      {"Kohl's - Dallas": 70.0,
'Bronx-Lebanon Hospital Center': 26.0}

Если словарь не то, что вам нужно, и вы настаиваете на том, чтобы вместо него был кортеж, вы можете использовать:

      list(resultDict.items())

Выход

      [("Kohl's - Dallas", 70.0), ('Bronx-Lebanon Hospital Center', 26.0)]
Другие вопросы по тегам