【问题标题】:Remove duplicates in one list and average corresponding list entries of another list删除一个列表中的重复项并平均另一个列表的相应列表条目
【发布时间】:2022-01-17 19:28:14
【问题描述】:

所以我有一个相当大的数据集,所以我需要编写一些高效的东西。 我的数据包含一个列表中各个艺术家的专辑发行年限和另一个列表中每张专辑的平均歌曲长度。

作为一个例子,这里是一些虚构的数据。此处以分钟为单位给出歌曲长度。

release_year=[2017,2017,2019,2020,2020,2021]
avg_songlength=[3,5,3,4,2,3]

我想获得一个数据集,它删除了 release_year 列表中的重复项,并且对于每个重复项,它再次平均歌曲长度。所以我想要得到的结果是:

years_without duplicates=[2017,2019,2020,2021]
avg_length_of_year=[3+5/2,3,4+2/2,3]

我发现 set() 可以有效地删除重复项,但我不知道如何在另一个列表中组合整个 有什么简单的方法可以做到这一点?

【问题讨论】:

  • 制作一个字典,其中年份是键,值是歌曲长度列表

标签: python arrays list data-science


【解决方案1】:

这是在基础 python 中解决此问题的一种简单方法。这里的想法是将我们在字典中看到的年份存储起来,并跟踪总歌曲运行时间以及对总数做出贡献的歌曲数量。然后最后我们可以检查字典中的键并将它们转换为平均运行时间。使用字典还有助于使这些数据比两个单独的列表更结构化。

release_year=[2017,2017,2019,2020,2020,2021]
avg_songlength=[3,5,3,4,2,3]

year_averages = dict()
for year, length in zip(release_year, avg_songlength):
    if year in year_averages:
        year_averages[year][0] += length
        year_averages[year][1] += 1
    else:
        year_averages[year] = [length, 1]

year_averages = {year: lst[0]/lst[1] for year, lst in year_averages.items()}
print(year_averages)

输出:

{2017: 4.0, 2019: 3.0, 2020: 3.0, 2021: 3.0}

【讨论】:

  • 感谢您的评论!我不能立即效仿这个例子。但我还是试过了。它给了我一个“关键错误:2021”。我的数据实际上并没有按年份排序。这会影响代码吗?
  • 对于这个解决方案来说,没有排序应该无关紧要,但我不确定为什么你会从这段代码中得到一个关键错误。什么输入给了你这个?
  • 哦,成功了!我不得不把它放在另一个函数中,我犯了一个愚蠢的错误。非常感谢!
  • 啊,当然!我很新在这里发帖^^
【解决方案2】:

一种选择是使用itertools.groupby

release_year=[2017,2017,2019,2020,2020,2021] 
avg_songlength=[3,5,3,4,2,3]

from itertools import groupby
from statistics import mean

years_without_duplicates, avg_length_of_year = zip(*(
             (k, mean(list(zip(*g))[1])) for k, g in
             groupby(sorted(zip(release_year, avg_songlength)),
                     lambda x: x[0]))
                                                  )

years_without_duplicates, avg_length_of_year
# ((2017, 2019, 2020, 2021), (4, 3, 3, 3))

或使用collections.defaultdict:

from collections import defaultdict

out = defaultdict(lambda : [0, 0]) # sum / count

for year, sl in zip(release_year, avg_songlength):
    out[year][0] += sl  # add length
    out[year][1] += 1   # increment counter of occurrences 
    
d = {k: v[0]/v[1] for k,v in out.items()} # avg = sum / count
years_without_duplicates, avg_length_of_year = zip(*d.items())

【讨论】:

  • 也想过这个,但是可读性不是很好,尤其是对于初学者。我责怪groupby 而不是你的代码,特别是返回嵌套迭代器
  • @Chris_Rands 我同意,我想要一个可以单独分组的groupby。我提供了另一种方法;)
【解决方案3】:

转换为 Pandas 数据框并使用聚合函数作为 np.mean

import pandas as pd
import numpy as np

df = pd.DataFrame({"release_year":[2017,2017,2019,2020,2020,2021],"avg_song_length":[3,5,3,4,2,3]})

print(df)

print(df.groupby("release_year",as_index=False).agg(avg_length_of_year=("avg_song_length",np.mean)))

【讨论】:

    【解决方案4】:

    这是一种简单的方法,使用一个字典来存储每年值的总和,另一个来计算添加了多少值。

    avg_dict = {}
    count_dict = {}
    
    for i in range(0, len(release_year)):
        if str(release_year[i]) in avg_dict:
            avg_dict[str(release_year[i])] = avg_dict[str(release_year[i])] + avg_songlength[i]
            count_dict[str(release_year[i])] = count_dict[str(release_year[i])] + 1
        else:
            avg_dict[str(release_year[i])] = avg_songlength[i]
            count_dict[str(release_year[i])] = 1
    
    for key in avg_dict:
        avg_dict[key] = avg_dict[key] / count_dict[key]
    
    print(avg_dict) # {'2017': 4.0, '2019': 3.0, '2020': 3.0, '2021': 3.0}
    

    【讨论】:

      猜你喜欢
      • 2022-01-17
      • 2022-06-16
      • 1970-01-01
      • 2019-05-11
      • 1970-01-01
      • 2021-09-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多