У меня есть списки идентификаторов и оценки:

ids=[1,2,1,1,3,1]
scores=[10,20,10,30,40,10]

Я хочу удалить дубликаты из идентификаторов списка, чтобы результаты суммировались соответствующим образом. Это очень похоже на то, что делает groupby.sum () при использовании фреймов данных.

Итак, в качестве результата я ожидаю:

ids=[1,2,3]
scores=[60,20,40]

Я использую следующий код, но он работает не во всех случаях:

for indi ,i in enumerate(ids):
     for indj ,j in enumerate(ids):
           if(i==j) and (indi!=indj):
                  del ids[i]
                  scores[indj]=scores[indi]+scores[indj]
                  del scores[indi]
0
AlexCh 4 Июл 2019 в 20:55

6 ответов

Лучший ответ

Как предлагается в комментариях, использование словаря является одним из способов. Вы можете выполнить итерацию один раз по списку и обновить сумму по идентификатору.

Если вам нужны два списка в конце, выберите из словаря keys и values с помощью методов keys() и values():

ids=[1,2,1,1,3,1]
scores=[10,20,10,30,40,10]

# Init the idct with all ids at 0
dict_ = {i:0 for i in set(ids)}
for id, scores in zip(ids, scores):
    dict_[id] += scores

print(dict_)
# {1: 60, 2: 20, 3: 40}

new_ids = list(dict_.keys())
sum_score = list(dict_.values())
print(new_ids)
# [1, 2, 3]
print(sum_score)
# [60, 20, 40]
0
Alexandre B. 4 Июл 2019 в 18:06

Вы можете создать словарь, используя ids и scores с ключом в качестве элементов id и значениями в виде списка элементов, соответствующих элементу в id, вы можете суммировать их до значений и получите ваш новый id и scores список

from collections import defaultdict

ids=[1,2,1,1,3,1]
scores=[10,20,10,30,40,10]

dct = defaultdict(list)

#Create the dictionary of element of ids vs list of elements of scores
for id, score in zip(ids, scores):
    dct[id].append(score)

print(dct)
#defaultdict(<class 'list'>, {1: [10, 10, 30, 10], 2: [20], 3: [40]})

#Calculate the sum of values, and get the new ids and scores list
new_ids, new_scores = zip(*((key, sum(value)) for key, value in dct.items()))

print(list(new_ids))
print(list(new_scores))

Выход будет

[1, 2, 3]
[60, 20, 40]
1
Devesh Kumar Singh 4 Июл 2019 в 18:03

Просто прокрутите их и добавьте, если идентификаторы совпадают.

ids=[1,2,1,1,3,1]
scores=[10,20,10,30,40,10]
ans={}
for i,s in zip(ids,scores):
    if i in ans:
        ans[i]+=s
    else:
        ans[i]=s
ids, scores=list(ans.keys()), list(ans.values())

Выход:

[1, 2, 3]
[60, 20, 40]
0
Ricky Kim 4 Июл 2019 в 18:08

Используя только встроенные инструменты Python, я бы выполнил эту задачу следующим образом:

ids=[1,2,1,1,3,1]
scores=[10,20,10,30,40,10]
uids = list(set(ids)) # unique ids
for uid in uids:
    print(uid,sum(s for inx,s in enumerate(scores) if ids[inx]==uid))

Выход:

1 60
2 20
3 40

Выше кода просто print результат, но его можно легко изменить, чтобы получить результат dict:

output_dict = {uid:sum(s for inx,s in enumerate(scores) if ids[inx]==uid) for uid in uids} # {1: 60, 2: 20, 3: 40}

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

0
Daweo 4 Июл 2019 в 18:34

Это может помочь вам.

#  Solution 1
import pandas as pd

ids=[1,2,1,1,3,1]
scores=[10,20,10,30,40,10]

df = pd.DataFrame(list(zip(ids, scores)),
                  columns=['ids', 'scores'])


print(df.groupby('ids').sum())

#### Output  ####

     scores
ids        
1        60
2        20
3        40


#  Solution 2
from itertools import groupby
zipped_list  = list(zip(ids, scores))
print([[k, sum(v for _, v in g)] for k, g in groupby(sorted(zipped_list), key = lambda x: x[0])])

#### Output  ####

[[1, 60], [2, 20], [3, 40]]
0
Preetham 4 Июл 2019 в 18:20
# Find all unique ids and keep track of their scores
id_to_score = {id : 0 for id in set(ids)}

# Sum up the scores for that id
for index, id in enumerate(ids):
    id_to_score[id] += scores[index]

unique_ids = []
score_sum = []
for (i, s) in id_to_score.items():
    unique_ids.append(i)
    score_sum.append(s)

print(unique_ids) # [1, 2, 3]
print(score_sum)  # [60, 20, 40]
0
fizzybear 4 Июл 2019 в 18:09