【问题标题】:Using Counter() in Python to build histogram?在 Python 中使用 Counter() 构建直方图?
【发布时间】:2013-10-12 11:55:00
【问题描述】:

我在另一个问题上看到我可以使用Counter() 来计算一组字符串中出现的次数。所以如果我有['A','B','A','C','A','A'],我会得到Counter({'A':3,'B':1,'C':1})。但是现在,我如何使用这些信息来构建直方图?

【问题讨论】:

  • 如果你想构建直方图我建议你使用numpy和matplotlib
  • 看看matplotlib
  • 从技术上讲,一个直方图——它有成分(字母)和频率(它们出现的时间)。您是在问如何将其制成条形图?
  • 我在询问更多关于如何提取每个字母的信息。 Igonato 回答了我的问题。
  • 您始终可以在对象上使用helpdir 函数来找出可用的方法和属性。

标签: python histogram


【解决方案1】:

对于您的数据,最好使用条形图而不是直方图。看看这段代码:

from collections import Counter
import numpy as np
import matplotlib.pyplot as plt


labels, values = zip(*Counter(['A','B','A','C','A','A']).items())

indexes = np.arange(len(labels))
width = 1

plt.bar(indexes, values, width)
plt.xticks(indexes + width * 0.5, labels)
plt.show()

结果:

【讨论】:

  • 如果 OP 的数据最适合直方图怎么办?我知道游戏已经晚了,但我想更新您的答案以应用于直方图示例(但我不知道该怎么做)。这将回答问题的标题。
  • @ThomasMatthew 从技术上讲,它是一个直方图。 “条形图而不是直方图”更多是指使用matplotlib.pyplot.bar而不是matplotlib.pyplot.hist。我相信bar 更适合Counter(这是 OP 想要的),就是这样
  • 这也是一个 3 年前的问题,有些东西可能已经改变了
  • @ThomasMatthew 您是如何到达那里的,您在寻找什么? google 评分高吗?什么查询?如果它显示在python Counter matplotlib 以外的其他内容上,那么编辑答案可能是有意义的
  • 我搜索了“从计数器构建直方图”,它是 Google 搜索结果 #1。这也几乎与OP问题的标题相同。对于所有搜索该查询的人来说,值得更新,这可能是这个问题的高百分比视图。您更新(添加)直方图示例可能会获得更多投票和收藏夹
【解决方案2】:

您可以使用pandas 编写一些非常简洁的代码来执行此操作:

    import numpy as np

    from pandas import Series
    
    sample = np.random.choice(['a', 'b'], size=10)
    
    s = Series(sample)
    
    In [29]: s
    Out[29]:
    0    a
    1    b
    2    b
    3    b
    4    a
    5    b
    6    b
    7    b
    8    b
    9    a
    dtype: object
    
    vc = s.value_counts()
    
    In [31]: vc
    Out[31]:
    b    7
    a    3
    dtype: int64
    
    vc = vc.sort_index()
    
    In [33]: vc
    Out[33]:
    a    3
    b    7
    dtype: int64
    
    c.plot(kind='bar')

导致:

【讨论】:

  • 但是 OP 专门询问了Counter。要回答这个问题,您应该展示如何从 Counter 转到 Series,除非有另一种更适合字典的 Pandas 类型。目前尚不清楚您的解决方案是否真的适用于此 - 它只是条形图的一个示例。
【解决方案3】:

根据 Igonato 的回答,我创建了一个带有“Plot”类的辅助模块“plot”。

它有两个函数 hist() 和 barchart() 两个显示 Igonato 的方法以及直接使用 matplotlib hist 功能,这可能是问题中最初的打算。

该方法允许添加具有给定字体大小的标题和标签,并以 1 的刻度频率显示 y 轴。您还可以更改模式以保存具有给定标题的图表。为方便起见,有关闭和调试选项。

python 单元测试 test_Plot.py

'''
Created on 2020-07-05

@author: wf
'''
import unittest


from ptp.plot import Plot

class TestPlot(unittest.TestCase):


    def setUp(self):
        pass


    def tearDown(self):
        pass


    def testPlot(self):
        ''' test a plot based on a Counter '''
        valueList=['A','B','A','C','A','A'];
        plot=Plot(valueList,"barchart example",xlabel="Char",ylabel="frequency")
        plot.barchart(mode='save')
        plot.title="histogram example"
        plot.debug=True
        plot.hist(mode='save')        
        pass


if __name__ == "__main__":
    #import sys;sys.argv = ['', 'Test.testName']
    unittest.main()

结果:

调试输出:

   value  list:  ['A', 'B', 'A', 'C', 'A', 'A']
counter  items:  dict_items([('A', 4), ('B', 1), ('C', 1)])
counter values:  dict_values([4, 1, 1])
counter   keys:  dict_keys(['A', 'B', 'C'])

plot.py

    '''
Created on 2020-07-05

@author: wf
'''
import matplotlib.pyplot as plt
from collections import Counter
import numpy as np
import os

class Plot(object):
    '''
    create Plot based on counters
    see https://stackoverflow.com/questions/19198920/using-counter-in-python-to-build-histogram
    '''
    def __init__(self, valueList,title,xlabel=None,ylabel=None,fontsize=12,plotdir=None,debug=False):
        '''
        Constructor
        '''
        self.counter=Counter(valueList)
        self.valueList=valueList
        self.title=title
        self.xlabel=xlabel
        self.ylabel=ylabel
        self.fontsize=fontsize
        self.debug=debug
        path=os.path.dirname(__file__)
        if plotdir is not None:
            self.plotdir=plotdir
        else:
            self.plotdir=path+"/../plots/"
            os.makedirs(self.plotdir,exist_ok=True)
            
    def titleMe(self):        
        plt.title(self.title, fontsize=self.fontsize)
        if self.xlabel is not None:
            plt.xlabel(self.xlabel)
        if self.ylabel is not None:    
            plt.ylabel(self.ylabel)
            
    def showMe(self,mode='show',close=True):
        ''' show me in the given mode '''
        if mode=="show":
            plt.show() 
        else:
            plt.savefig(self.plotdir+self.title+".jpg")
        if close:    
            plt.close()    
            
    def barchart(self,mode='show'):
        ''' barchart based histogram for the given counter '''
        labels, values = zip(*self.counter.items())
        indexes = np.arange(len(labels))
        width = 1
        self.titleMe()
        plt.bar(indexes, values, width)
        plt.xticks(indexes + width * 0.5, labels)
        plt.yticks(np.arange(1,max(values)+1,step=1))
        self.showMe(mode)
        
    def showDebug(self):    
        print("   value  list: ",self.valueList)
        print("counter  items: ",self.counter.items())
        print("counter values: ",self.counter.values())
        print("counter   keys: ",self.counter.keys())
        
    def hist(self,mode="show"):
        ''' create histogram for the given counter '''
        if self.debug:
            self.showDebug()
        self.titleMe()
        # see https://stackoverflow.com/a/2162045/1497139
        plt.hist(self.valueList,bins=len(self.counter.keys()))
        self.showMe(mode)
        pass
        
    

【讨论】:

  • 一个简洁的实现!
猜你喜欢
  • 2013-03-06
  • 1970-01-01
  • 2022-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多