【问题标题】:Finding the mode of a list查找列表的模式
【发布时间】:2012-06-03 14:21:25
【问题描述】:

给定一个项目列表,回忆一下列表的模式是最常出现的项目。

我想知道如何创建一个函数,它可以找到列表的模式,但如果列表没有模式(例如,列表中的所有项目只出现一次),它会显示一条消息。我想在不导入任何功能的情况下制作此功能。我正在尝试从头开始制作自己的功能。

【问题讨论】:

  • 抱歉,您能解释一下“列表模式”的确切含义吗?
  • @Vikas:模式是最常出现的元素(如果有的话)。如果有多个元素,一些定义将其扩展为采用所有此类元素的算术平均值。
  • 这里有很多错误的答案!例如 assert(mode[1, 1, 1]) == Noneassert(mode[1, 2, 3, 4]) == None。对于要成为mode 的数字,它必须比列表中至少一个其他数字出现的次数更多,并且它必须不是是列表中的唯一数字。

标签: python mode


【解决方案1】:

您可以使用max 功能和一个键。看看python max function using 'key' and lambda expression

max(set(lst), key=lst.count)

【讨论】:

  • 这是 OP 的正确答案,因为它不需要任何额外的导入。干得好,大卫
  • 在我看来这将在O(n**2) 中运行。是吗?
  • 这有二次运行时间
  • 也可以只使用max(lst, key=lst.count)。 (而且我真的不会调用列表list。)
  • 谁能解释这对双峰分布是如何工作的?例如a = [22, 33, 11, 22, 11]; print(max(set(a), key=a.count)) 返回11。它会一直返回最小模式吗?如果是这样,为什么?
【解决方案2】:

您可以使用collections 包中提供的Counter,它具有mode-esque 函数

from collections import Counter
data = Counter(your_list_in_here)
data.most_common()   # Returns all unique items and their counts
data.most_common(1)  # Returns the highest occurring item

注意:计数器是 python 2.7 中的新功能,在早期版本中不可用。

【讨论】:

  • 问题表明用户想要从头开始创建一个函数——即没有导入。
  • 您的最后一行返回一个列表,其中包含一个包含模式及其频率的元组。要获得一种模式,请使用Counter(your_list_in_here).most_common(1)[0][0]。如果有多个模式,则返回任意模式。
  • 假设有n最常见的modes。如果 Counter(your_list_in_here).most_common(1)[0][0] 让您获得第一种模式,您将如何获得另一个最常见的 mode ?只需将最后一个0 替换为1?可以根据自己的喜好制作一个功能来自定义mode..
  • 如果有多个模式,如何返回这些数字中最大的一个?
【解决方案3】:

Python 3.4 包含方法statistics.mode,所以很简单:

>>> from statistics import mode
>>> mode([1, 1, 2, 3, 3, 3, 3, 4])
 3

列表中可以有任何类型的元素,而不仅仅是数字:

>>> mode(["red", "blue", "blue", "red", "green", "red", "red"])
 'red'

【讨论】:

  • 在使用 mode([1, 1,1,1, 2, 3, 3, 3, 3, 4]) 时抛出错误,其中 1 和 3 重复相同的次数。理想情况下,应该返回最大但相同次数的最小数。 StatisticsError:没有唯一模式;找到 2 个同样常见的值
  • 没有使用过这个 3.4 的统计包,但是 scipy.stats.mode 会返回最小的,在这种情况下是 1。然而,在某些情况下我更喜欢抛出错误......
  • @aman_novice,该问题已在 Python 3.8 中解决。 docs.python.org/3/library/statistics.html#statistics.mode
  • python 3.8还增加了multimode,当有多个模式时返回多种模式。
【解决方案4】:

借鉴一些统计软件,即SciPyMATLAB,它们只返回最小最常见的值,因此如果两个值出现的频率相同,则返回其中最小的值。希望一个例子会有所帮助:

>>> from scipy.stats import mode

>>> mode([1, 2, 3, 4, 5])
(array([ 1.]), array([ 1.]))

>>> mode([1, 2, 2, 3, 3, 4, 5])
(array([ 2.]), array([ 2.]))

>>> mode([1, 2, 2, -3, -3, 4, 5])
(array([-3.]), array([ 2.]))

你有什么理由不能遵守这个约定吗?

【讨论】:

  • 为什么有多个时只返回最小的模式?
  • @zyxue 简单统计约定
  • @chrisfs 如果有多个,让它返回最大的模式?
【解决方案5】:

在Python中有很多简单的方法来查找列表的模式,例如:

import statistics
statistics.mode([1,2,3,3])
>>> 3

或者,您可以通过计数找到最大值

max(array, key = array.count)

这两种方法的问题在于它们不适用于多种模式。第一个返回错误,而第二个返回第一个模式。

为了找到一个集合的模式,你可以使用这个函数:

def mode(array):
    most = max(list(map(array.count, array)))
    return list(set(filter(lambda x: array.count(x) == most, array)))

【讨论】:

  • 使用该模式,当两个元素出现相同的时间时会出错。
  • 抱歉,很晚才看到这条评论。 Statistics.mode(array) 会在多种模式下返回错误,但其他方法都不会。
  • (1) 被描述为频率最高的数据点 (2) 数据集中可以有多种模式 (3) 如果是连续值,可能无法找到模式(因为所有值都是唯一的)(4)它也可以用于非数字数据
【解决方案6】:

扩展列表为空时不起作用的社区答案,这里是模式的工作代码:

def mode(arr):
        if arr==[]:
            return None
        else:
            return max(set(arr), key=arr.count)

【讨论】:

    【解决方案7】:

    如果您对最小、最大或所有模式感兴趣:

    def get_small_mode(numbers, out_mode):
        counts = {k:numbers.count(k) for k in set(numbers)}
        modes = sorted(dict(filter(lambda x: x[1] == max(counts.values()), counts.items())).keys())
        if out_mode=='smallest':
            return modes[0]
        elif out_mode=='largest':
            return modes[-1]
        else:
            return modes
    

    【讨论】:

      【解决方案8】:

      我写了这个方便的函数来查找模式。

      def mode(nums):
          corresponding={}
          occurances=[]
          for i in nums:
                  count = nums.count(i)
                  corresponding.update({i:count})
      
          for i in corresponding:
                  freq=corresponding[i]
                  occurances.append(freq)
      
          maxFreq=max(occurances)
      
          keys=corresponding.keys()
          values=corresponding.values()
      
          index_v = values.index(maxFreq)
          global mode
          mode = keys[index_v]
          return mode
      

      【讨论】:

      • 如果两个项目的编号相同,此方法将失败。发生次数。
      【解决方案9】:

      短,但有点丑:

      def mode(arr) :
          m = max([arr.count(a) for a in arr])
          return [x for x in arr if arr.count(x) == m][0] if m>1 else None
      

      使用字典,不那么难看:

      def mode(arr) :
          f = {}
          for a in arr : f[a] = f.get(a,0)+1
          m = max(f.values())
          t = [(x,f[x]) for x in f if f[x]==m]
          return m > 1 t[0][0] else None
      

      【讨论】:

        【解决方案10】:

        稍长一点,但可以有多种模式,并且可以获得具有最多计数或混合数据类型的字符串。

        def getmode(inplist):
            '''with list of items as input, returns mode
            '''
            dictofcounts = {}
            listofcounts = []
            for i in inplist:
                countofi = inplist.count(i) # count items for each item in list
                listofcounts.append(countofi) # add counts to list
                dictofcounts[i]=countofi # add counts and item in dict to get later
            maxcount = max(listofcounts) # get max count of items
            if maxcount ==1:
                print "There is no mode for this dataset, values occur only once"
            else:
                modelist = [] # if more than one mode, add to list to print out
                for key, item in dictofcounts.iteritems():
                    if item ==maxcount: # get item from original list with most counts
                        modelist.append(str(key))
                print "The mode(s) are:",' and '.join(modelist)
                return modelist 
        

        【讨论】:

          【解决方案11】:

          要使一个数字成为mode,它出现的次数必须多于列表中至少一个其他数字,并且它必须是列表中的唯一数字。所以,我重构了@mathwizurd 的答案(使用difference 方法)如下:

          def mode(array):
              '''
              returns a set containing valid modes
              returns a message if no valid mode exists
                - when all numbers occur the same number of times
                - when only one number occurs in the list 
                - when no number occurs in the list 
              '''
              most = max(map(array.count, array)) if array else None
              mset = set(filter(lambda x: array.count(x) == most, array))
              return mset if set(array) - mset else "list does not have a mode!" 
          

          这些测试成功通过:

          mode([]) == None 
          mode([1]) == None
          mode([1, 1]) == None 
          mode([1, 1, 2, 2]) == None 
          

          【讨论】:

            【解决方案12】:

            为什么不直接

            def print_mode (thelist):
              counts = {}
              for item in thelist:
                counts [item] = counts.get (item, 0) + 1
              maxcount = 0
              maxitem = None
              for k, v in counts.items ():
                if v > maxcount:
                  maxitem = k
                  maxcount = v
              if maxcount == 1:
                print "All values only appear once"
              elif counts.values().count (maxcount) > 1:
                print "List has multiple modes"
              else:
                print "Mode of list:", maxitem
            

            它没有一些它应该有的错误检查,但它会在不导入任何函数的情况下找到模式,并且如果所有值只出现一次,它将打印一条消息。它还将检测共享相同最大计数的多个项目,尽管尚不清楚您是否想要这样做。

            【讨论】:

            • 所以我想要做的是检测显示相同计数的多个项目,然后显示具有相同计数的所有项目
            • 你自己试过吗?我的代码在这里的扩展让它打印具有相同计数的所有项目非常简单。
            【解决方案13】:

            此函数返回一个或多个函数的模式(无论有多少),以及数据集中的一个或多个模式的频率。如果没有模式(即所有项目只出现一次),该函数将返回一个错误字符串。这类似于上面 A_nagpal 的函数,但在我看来,它更完整,而且我认为对于任何阅读此问题的 Python 新手(例如你的真正的)来说更容易理解。

             def l_mode(list_in):
                count_dict = {}
                for e in (list_in):   
                    count = list_in.count(e)
                    if e not in count_dict.keys():
                        count_dict[e] = count
                max_count = 0 
                for key in count_dict: 
                    if count_dict[key] >= max_count:
                        max_count = count_dict[key]
                corr_keys = [] 
                for corr_key, count_value in count_dict.items():
                    if count_dict[corr_key] == max_count:
                        corr_keys.append(corr_key)
                if max_count == 1 and len(count_dict) != 1: 
                    return 'There is no mode for this data set. All values occur only once.'
                else: 
                    corr_keys = sorted(corr_keys)
                    return corr_keys, max_count
            

            【讨论】:

            • 我这么说只是因为您说“函数返回错误字符串”。读取return 'There is no mode for this data set. All values occur only once.' 的行可以变成错误消息,traceback as `if condition: next line with indent raise ValueError('There is no mode for this data set. All values are occured只有一次。') Here is a list 您可以提出不同类型的错误。
            【解决方案14】:

            这将返回所有模式:

            def mode(numbers)
                largestCount = 0
                modes = []
                for x in numbers:
                    if x in modes:
                        continue
                    count = numbers.count(x)
                    if count > largestCount:
                        del modes[:]
                        modes.append(x)
                        largestCount = count
                    elif count == largestCount:
                        modes.append(x)
                return modes
            

            【讨论】:

              【解决方案15】:

              对于那些寻找最小模式的人,例如:双模式分布的情况,使用 numpy。

              import numpy as np
              mode = np.argmax(np.bincount(your_list))
              

              【讨论】:

                【解决方案16】:

                无需任何导入即可找到列表模式的简单代码:

                nums = #your_list_goes_here
                nums.sort()
                counts = dict()
                for i in nums:
                    counts[i] = counts.get(i, 0) + 1
                mode = max(counts, key=counts.get)
                

                如果是多种模式,应该返回最小节点。

                【讨论】:

                  【解决方案17】:

                  数据集的众数是该集中出现频率最高的成员。如果有两个成员出现次数最多且次数相同,则数据有两种模式。这称为双峰。

                  如果有超过 2 种模式,则数据将被称为多峰。如果数据集中所有成员出现的次数相同,则数据集根本没有众数。

                  以下函数模式()可以在给定的数据列表中查找模式:

                  import numpy as np; import pandas as pd
                  
                  def modes(arr):
                      df = pd.DataFrame(arr, columns=['Values'])
                      dat = pd.crosstab(df['Values'], columns=['Freq'])
                      if len(np.unique((dat['Freq']))) > 1:
                          mode = list(dat.index[np.array(dat['Freq'] == max(dat['Freq']))])
                          return mode
                      else:
                          print("There is NO mode in the data set")
                  

                  输出:

                  # For a list of numbers in x as
                  In [1]: x = [2, 3, 4, 5, 7, 9, 8, 12, 2, 1, 1, 1, 3, 3, 2, 6, 12, 3, 7, 8, 9, 7, 12, 10, 10, 11, 12, 2]
                  In [2]: modes(x)
                  Out[2]: [2, 3, 12]
                  # For a list of repeated numbers in y as
                  In [3]: y = [2, 2, 3, 3, 4, 4, 10, 10]
                  In [4]: modes(y)
                  Out[4]: There is NO mode in the data set
                  # For a list of strings/characters in z as
                  In [5]: z = ['a', 'b', 'b', 'b', 'e', 'e', 'e', 'd', 'g', 'g', 'c', 'g', 'g', 'a', 'a', 'c', 'a']
                  In [6]: modes(z)
                  Out[6]: ['a', 'g']
                  

                  如果我们不想导入numpypandas 来调用这些包中的任何函数,那么为了得到同样的输出,modes() 函数可以写成:

                  def modes(arr):
                      cnt = []
                      for i in arr:
                          cnt.append(arr.count(i))
                      uniq_cnt = []
                      for i in cnt:
                          if i not in uniq_cnt:
                              uniq_cnt.append(i)
                      if len(uniq_cnt) > 1:
                          m = []
                          for i in list(range(len(cnt))):
                              if cnt[i] == max(uniq_cnt):
                                  m.append(arr[i])
                          mode = []
                          for i in m:
                              if i not in mode:
                                  mode.append(i)
                          return mode
                      else:
                          print("There is NO mode in the data set")
                  

                  【讨论】:

                    【解决方案18】:

                    好吧!所以社区已经有很多答案,其中一些使用了另一个功能,而你不想要。
                    让我们创建我们的非常简单易懂的函数。

                    import numpy as np
                    
                    #Declare Function Name
                    def calculate_mode(lst):
                    

                    下一步是在列表中查找唯一元素及其各自的频率

                    unique_elements,freq = np.unique(lst, return_counts=True)
                    

                    获取模式

                    max_freq = np.max(freq)   #maximum frequency
                    mode_index = np.where(freq==max_freq)  #max freq index
                    mode = unique_elements[mode_index]   #get mode by index
                    return mode
                    

                    例子

                    lst =np.array([1,1,2,3,4,4,4,5,6])
                    print(calculate_mode(lst))
                    >>> Output [4]
                    

                    【讨论】:

                      【解决方案19】:
                      def mode(inp_list):
                          sort_list = sorted(inp_list)
                          dict1 = {}
                          for i in sort_list:        
                                  count = sort_list.count(i)
                                  if i not in dict1.keys():
                                      dict1[i] = count
                      
                          maximum = 0 #no. of occurences
                          max_key = -1 #element having the most occurences
                      
                          for key in dict1:
                              if(dict1[key]>maximum):
                                  maximum = dict1[key]
                                  max_key = key 
                              elif(dict1[key]==maximum):
                                  if(key<max_key):
                                      maximum = dict1[key]
                                      max_key = key
                      
                          return max_key
                      

                      【讨论】:

                        【解决方案20】:
                        def mode(data):
                            lst =[]
                            hgh=0
                            for i in range(len(data)):
                                lst.append(data.count(data[i]))
                            m= max(lst)
                            ml = [x for x in data if data.count(x)==m ] #to find most frequent values
                            mode = []
                            for x in ml: #to remove duplicates of mode
                                if x not in mode:
                                mode.append(x)
                            return mode
                        print mode([1,2,2,2,2,7,7,5,5,5,5])
                        

                        【讨论】:

                          【解决方案21】:

                          这是一个简单的函数,用于获取列表中出现的第一个模式。它以列表元素作为键和出现次数创建一个字典,然后读取字典值以获取模式。

                          def findMode(readList):
                              numCount={}
                              highestNum=0
                              for i in readList:
                                  if i in numCount.keys(): numCount[i] += 1
                                  else: numCount[i] = 1
                              for i in numCount.keys():
                                  if numCount[i] > highestNum:
                                      highestNum=numCount[i]
                                      mode=i
                              if highestNum != 1: print(mode)
                              elif highestNum == 1: print("All elements of list appear once.")
                          

                          【讨论】:

                            【解决方案22】:

                            如果您想要一种清晰的方法,对课堂有用并且仅通过理解使用列表和字典,您可以这样做:

                            def mode(my_list):
                                # Form a new list with the unique elements
                                unique_list = sorted(list(set(my_list)))
                                # Create a comprehensive dictionary with the uniques and their count
                                appearance = {a:my_list.count(a) for a in unique_list} 
                                # Calculate max number of appearances
                                max_app = max(appearance.values())
                                # Return the elements of the dictionary that appear that # of times
                                return {k: v for k, v in appearance.items() if v == max_app}
                            

                            【讨论】:

                              【解决方案23】:
                              #function to find mode
                              def mode(data):  
                                  modecnt=0
                              #for count of number appearing
                                  for i in range(len(data)):
                                      icount=data.count(data[i])
                              #for storing count of each number in list will be stored
                                      if icount>modecnt:
                              #the loop activates if current count if greater than the previous count 
                                          mode=data[i]
                              #here the mode of number is stored 
                                          modecnt=icount
                              #count of the appearance of number is stored
                                  return mode
                              print mode(data1)
                              

                              【讨论】:

                              • 你应该用 cmets 或更多细节来解释你的答案
                              【解决方案24】:

                              您可以通过以下方式找到列表的均值、中位数和众数:

                              import numpy as np
                              from scipy import stats
                              
                              #to take input
                              size = int(input())
                              numbers = list(map(int, input().split()))
                              
                              print(np.mean(numbers))
                              print(np.median(numbers))
                              print(int(stats.mode(numbers)[0]))
                              

                              【讨论】:

                                【解决方案25】:
                                import numpy as np
                                def get_mode(xs):
                                    values, counts = np.unique(xs, return_counts=True)
                                    max_count_index = np.argmax(counts) #return the index with max value counts
                                    return values[max_count_index]
                                print(get_mode([1,7,2,5,3,3,8,3,2]))
                                

                                【讨论】:

                                  【解决方案26】:

                                  也许尝试以下方法。它是 O(n) 并返回浮点数(或整数)列表。它经过彻底的自动测试。它使用 collections.defaultdict,但我想您并不反对使用它。也可以在https://stromberg.dnsalias.org/~strombrg/stddev.html找到它

                                  def compute_mode(list_: typing.List[float]) -> typing.List[float]:
                                      """                       
                                      Compute the mode of list_.
                                  
                                      Note that the return value is a list, because sometimes there is a tie for "most common value".
                                                                                                          
                                      See https://stackoverflow.com/questions/10797819/finding-the-mode-of-a-list
                                      """                                                                                                        
                                      if not list_:
                                          raise ValueError('Empty list')
                                      if len(list_) == 1:           
                                          raise ValueError('Single-element list')
                                      value_to_count_dict: typing.DefaultDict[float, int] = collections.defaultdict(int)
                                      for element in list_:
                                          value_to_count_dict[element] += 1
                                      count_to_values_dict = collections.defaultdict(list)
                                      for value, count in value_to_count_dict.items():   
                                          count_to_values_dict[count].append(value)                           
                                      counts = list(count_to_values_dict)
                                      if len(counts) == 1:                                                                            
                                          raise ValueError('All elements in list are the same')          
                                      maximum_occurrence_count = max(counts)
                                      if maximum_occurrence_count == 1:
                                          raise ValueError('No element occurs more than once')
                                      minimum_occurrence_count = min(counts)
                                      if maximum_occurrence_count <= minimum_occurrence_count:
                                          raise ValueError('Maximum count not greater than minimum count')
                                      return count_to_values_dict[maximum_occurrence_count]
                                  

                                  【讨论】:

                                    猜你喜欢
                                    • 2019-11-29
                                    • 1970-01-01
                                    • 1970-01-01
                                    • 1970-01-01
                                    • 1970-01-01
                                    • 1970-01-01
                                    • 1970-01-01
                                    • 2011-05-28
                                    相关资源
                                    最近更新 更多