【问题标题】:Take the mean of values in a list if a duplicate is found如果发现重复项,则取列表中值的平均值
【发布时间】:2018-05-19 06:19:48
【问题描述】:

我有 2 个相互关联的列表。例如,在这里,'John' 与 '1' 相关联,'Bob' 与 4 相关联,依此类推:

l1 = ['John', 'Bob', 'Stew', 'John']
l2 = [1, 4, 7, 3]

我的问题是重复的约翰。我不想添加重复的 John,而是取与 Johns 相关的值的平均值,即 1 和 3,即 (3 + 1)/2 = 2。因此,我希望这些列表实际上是:

l1 = ['John', 'Bob', 'Stew']
l2 = [2, 4, 7]

我尝试了一些解决方案,包括 for 循环和“contains”函数,但似乎无法将它们拼凑起来。我对 Python 不是很有经验,但链表听起来可以用于此。

谢谢

【问题讨论】:

  • 炖肉不是和7关联的吗?
  • 也许你需要的是一个字典。你试过吗?
  • @schwobaseggl 抱歉,已修复 :)
  • @bla 是的,我确实尝试了一个 dict,但问题是,由于键只能是唯一的,因此我没有机会取 l2 中关联值的平均值,因为它会自动拒绝重复值。
  • @MythicCocoa 您可以尝试制作与'John' 关联的值列表,然后根据需要取平均值。看看这个答案,将多个值添加到字典中的同一个键:stackoverflow.com/a/47620204/3044673

标签: python arrays list for-loop append


【解决方案1】:

我认为您应该使用 dict。 :)

def mean_duplicate(l1, l2):
    ret = {}
    #   Iterating through both lists...
    for name, value in zip(l1, l2):
        if not name in ret:
            #   If the key doesn't exist, create it.
            ret[name] = value
        else:
            #   If it already does exist, update it.
            ret[name] += value

    #   Then for the average you're looking for...
    for key, value in ret.iteritems():
        ret[key] = value / l1.count(key)

    return ret

def median_between_listsElements(l1, l2):
    ret = {}

    for name, value in zip(l1, l2):
        #   Creating key + list if doesn't exist.
        if not name in ret:
            ret[name] = []
        ret[name].append(value)

    for key, value in ret.iteritems():
        ret[key] = np.median(value)

    return ret

l1 = ['John', 'Bob', 'Stew', 'John']
l2 = [1, 4, 7, 3]

print mean_duplicate(l1, l2)
print median_between_listsElements(l1, l2)
# {'Bob': 4, 'John': 2, 'Stew': 7}
# {'Bob': 4.0, 'John': 2.0, 'Stew': 7.0}

【讨论】:

  • AttributeError: 'dict' 对象没有属性 'iteritems'?
  • @MythicCocoa 您可能正在运行 python 3.x。 python 3 等价物是.items()
  • 很高兴知道:)。优雅的解决方案,完美运行,谢谢!
  • 嗨,很想知道如果取中位数而不是平均值会使这段代码更复杂
  • 为什么会这样?不过,它会稍微(一点)复杂一些。你试过什么?
【解决方案2】:

以下内容可能会给您一个想法。它使用OrderedDict 假设您希望项目按原始列表中的出现顺序排列:

from collections import OrderedDict

d = OrderedDict()
for x, y in zip(l1, l2):
    d.setdefault(x, []).get(x).append(y)
# OrderedDict([('John', [1, 3]), ('Bob', [4]), ('Stew', [7])])


names, values = zip(*((k, sum(v)/len(v)) for k, v in d.items()))
# ('John', 'Bob', 'Stew')
# (2.0, 4.0, 7.0)

【讨论】:

    【解决方案3】:

    这是一个使用 dict 的较短版本,

    final_dict = {}
    l1 = ['John', 'Bob', 'Stew', 'John']
    l2 = [1, 4, 7, 3]
    
    for i in range(len(l1)):
        if final_dict.get(l1[i]) == None:
            final_dict[l1[i]] = l2[i]
        else:
            final_dict[l1[i]] = int((final_dict[l1[i]] + l2[i])/2)
    
    
    print(final_dict)
    

    【讨论】:

      【解决方案4】:

      类似这样的:

      #!/usr/bin/python
      l1 = ['John', 'Bob', 'Stew', 'John']
      l2 = [1, 4, 7, 3]
      d={}
      for i in range(0, len(l1)):
          key = l1[i]
          if d.has_key(key):
               d[key].append(l2[i])
          else:
               d[key] = [l2[i]]
      r = []
      for values in d.values():
          r.append((key,sum(values)/len(values)))
      print r
      

      【讨论】:

        【解决方案5】:

        希望以下代码有所帮助

        l1 = ['John', 'Bob', 'Stew', 'John']
        l2 = [1, 4, 7, 3]
        
        def remove_repeating_names(names_list, numbers_list):
            new_names_list = []
            new_numbers_list = []
            for first_index, first_name in enumerate(names_list):
                amount_of_occurencies = 1
                number = numbers_list[first_index]
                for second_index, second_name in enumerate(names_list):
                    # Check if names match and
                    # if this name wasn't read in earlier cycles or is not same element.
                    if (second_name == first_name):
                        if (first_index < second_index):
                            number += numbers_list[second_index]
                            amount_of_occurencies += 1
                    # Break the loop if this name was read earlier.
                        elif (first_index > second_index):
                            amount_of_occurencies = -1
                            break
                if amount_of_occurencies is not -1:
                    new_names_list.append(first_name)
                    new_numbers_list.append(number/amount_of_occurencies)
            return [new_names_list, new_numbers_list]
        
        # Unmodified arrays
        print(l1)
        print(l2)
        
        l1, l2 = remove_repeating_names(l1, l2)
        
        # If you want numbers list to be integer, not float, uncomment following line:
        # l2 = [int(number) for number in l2]
        
        # Modified arrays
        print(l1)
        print(l2)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-03-15
          • 2023-03-04
          • 1970-01-01
          • 1970-01-01
          • 2020-12-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多