【问题标题】:How To Properly Create a Histogram: Displaying the Frequency of the Tweets for Each Day Spanning 2 Years如何正确创建直方图:显示 2 年内每天的推文频率
【发布时间】:2017-07-10 01:32:06
【问题描述】:

不幸的是,我完全没有使用 matplotlib(和类似库)的经验,而且我发现一些可用的教程令人困惑。

这是我的问题:

我有字符串格式的时间戳列表,如下所示:

timestamp_list = ['2017-01-30 23:45', '2017-01-30 20:30', '2017-01-30 18:22', '2017-01-29 17:39', '2017-01-29 15:39', '2017-01-29 14:45', '2017-01-29 11:51', '2017-01-29 11:15', '2017-01-29 09:41', '2017-01-30 05:54', '2017-01-29 03:10']

每个时间戳代表一条推文。我想建立一个类似于this 的直方图,但每天对我的推文进行分组。所以,最终,我希望这个直方图显示我的列表中每天有多少推文被发布。

我不知道如何每天(或任何其他分组,即每月)对这些推文进行分组。我不知道哪种方法最简单、最轻松,最重要的是,当我阅读有关如何使用 matplotlib 创建直方图(以及类似的东西,如 CDF)的帖子时,我不明白什么每一行具体都有,因此,我无法根据自己的需要编辑这些帖子并扩展我的知识。

有人可以提供一个示例解决方案来使用 matplotlib(或类似的)创建这样的直方图,但也可以评论每一行,以便我可以完全理解将来如何生成类似的图?

谢谢。


编辑:我认为我最初的问题不够清楚,因为建议的解决方案都没有解决我的问题。我很抱歉没有更明确。我会尽量详细说明:

假设我有一组特定主题的推文,时间跨度为两年。总计 730 天。 timestamp_list 是一个列表,其中包含每条推文的唯一时间戳,格式为 string

这两年的每一天都是独特的一天。这意味着我有 730 个独特的日子。我想要的是找出在这 730 天的每一天中有多少关于该特定主题的推文。例如,2017-01-20 上可能有 10 条推文,2017-01-21 上可能有 45 条推文,等等。我想基于此创建一个直方图。有人建议创建字典。

  • 如何创建包含 730 个键及其各自推文数量的字典?
  • 如何根据以前的字典绘制直方图?

或者,如果有其他更有效的方法(而不是使用字典),也欢迎。

我想要以某种方式获取这个string 列表并创建一个直方图like this,显示每天发布的推文数量,跨越日期的持续时间(在我的情况下,为 2 年)。


赏金

感谢大家的提交。 @cphlewis 和 @TobiasRibizel 的答案都是正确的。但是,我倾向于选择@TobiasRibizel 的答案作为获胜答案,因为它不使用第三方库,解释得很好,并且它产生了一个非常漂亮的直方图,就像我问的那样。谢谢你。

【问题讨论】:

    标签: python python-3.x matplotlib twitter


    【解决方案1】:

    新的解决方案,采用了 Tobias 的评论——一旦时间戳被分解成感兴趣的部分,直方图就会被构建到 pandas 中并且是“智能日期”,也就是说,它将离开 x 轴没有推文的日期空间:

    import pandas as pd
    import matplotlib.pyplot as plt
    
    timestamp_list = ['2017-01-15 23:45', '2017-01-16 20:30', '2017-01-30 18:22',
                      '2017-01-29 17:39', '2017-01-29 15:39', '2017-01-29 14:45',
                      '2017-01-29 11:51', '2017-01-29 11:15', '2017-01-29 09:41',
                      '2017-01-30 05:54', '2017-01-29 03:10','2016-05-02 00:00',
                      '2016-05-23 00:00', '2016-03-29 00:00']
    
    Tweetframe = pd.DataFrame(pd.to_datetime(timestamp_list), columns=['Tweets'])
    Tweetframe['Date'] = map(lambda x: x.date(), Tweetframe.Tweets)
    
    # Tweetframe.Date is a Series, which has a histogram method.
    # By default it uses 10 bins; this sets the bins to number of days
    # Nb: which is not exactly the same as grouping by Date. 
    ax = Tweetframe.Date.hist(xrot=45,
                              bins = (Tweetframe.Date.max() -
                                          Tweetframe.Date.min()).days)
    
    ax.set_ylabel('Tweet count')
    ax.grid('off')
    plt.show()
    

    离开:我想到的第一件事,它在 x 轴值中是精确的,但你必须大惊小怪才能让 x 轴间距来处理无推文的日期:

    import pandas as pd
    import matplotlib.pyplot as plt
    timestamp_list = ['2017-01-30 23:45', '2017-01-30 20:30', '2017-01-30 18:22', '2017-01-29 17:39', '2017-01-29 15:39', '2017-01-29 14:45', '2017-01-29 11:51', '2017-01-29 11:15', '2017-01-29 09:41', '2017-01-30 05:54', '2017-01-29 03:10','2016-01-30 00:00','2016-01-29 00:00', '2017-03-29 00:00']
    
    
    
    # Pandas works on DataFrames, so make a DataFrame. Make real datetimes because Pandas is also smart about datetimes: 
    Tweetframe = pd.DataFrame(pd.to_datetime(timestamp_list), columns=['Tweets'])
    # The groupby function groups the data by the cases given in the first argument; the result is a DataFrameGroupBy object, sort of a tiny database, which can count the elements in each group and then barplot the counts:
    Tweetframe.groupby((Tweetframe['Tweets'].dt.year, Tweetframe['Tweets'].dt.month, Tweetframe['Tweets'].dt.day)).count().plot(kind="bar")
    # I always need to do something to date-stamp xlabels to make them readable
    plt.xticks(rotation=0)
    plt.show()
    

    【讨论】:

    • 能否修改您的解决方案以包括未发布推文的日子?这样,x 轴会更加连续。
    【解决方案2】:

    最简单的解决方案可能是将字符串解析为date 对象,并使用pyplot 的hist 从该数据中创建直方图:

    from datetime import date, timedelta
    import matplotlib.pyplot as plt
    
    # these lines are just there to create some data
    from random import randint
    from datetime import datetime
    timestamp_list = [datetime(2017,randint(4,6),randint(1,30),randint(0,23),randint(0,59)).strftime("%Y-%m-%d %h:%m") for i in range(1000)]
    
    # here the real code starts
    dates = []
    for t in timestamp_list:
        # extract the date part of the timestamp
        date_str = t.split(' ')[0]
        # extract the numbers from the date
        year,month,day = [int(i) for i in date_str.split('-')]
        # create a date object
        d = date(year, month, day)
        # and store it
        dates.append(d)
    
    # sort the dates
    dates.sort()
    
    # extract the first and last date
    min_date = dates[0]
    max_date = dates[-1]
    
    # compute the number of days
    length = (max_date - min_date).days + 1
    
    # show the histogram
    plt.hist(dates, bins=length)
    plt.show()
    

    如果您想对绘图的外观进行更多控制,我建议您自己为直方图创建桶并使用bar 绘图:

    # initialize one empty bucket per day
    buckets = [0 for i in range(length)]
    days = [(min_date + timedelta(i)).isoformat() for i in range(length)]
    
    for d in dates:
        days_from_begin = (d - min_date).days
        buckets[days_from_begin] += 1
    
    # print a bar plot of the results
    plt.bar(range(length), buckets)
    # add x-axis ticks (dates)
    plt.xticks(range(length), days, rotation=70)
    
    # some cosmetics: hide all ticks
    plt.setp(plt.gca().get_xticklabels(), visible=False)
    # show every 4th tick again
    plt.setp(plt.gca().get_xticklabels()[::4],visible=True)
    
    # show the result
    plt.show()
    

    输出可能如下所示:

    【讨论】:

      【解决方案3】:

      您可以使用默认字典并按日期对它们进行分组,如下所示:

      from collections import defaultdict
      
      
      groups = defaultdict(list)
      timestamp_list = ['2017-01-30 23:45', '2017-01-30 20:30', '2017-01-30 18:22', '2017-01-29 17:39', '2017-01-29 15:39', '2017-01-29 14:45', '2017-01-29 11:51', '2017-01-29 11:15', '2017-01-29 09:41', '2017-01-30 05:54', '2017-01-29 03:10']
      
      for obj in timestamp_list:
          groups[obj[8:-6]].append(obj)
      
      new_list = list(groups.values())
      
      print(new_list)
      
      
      [
       ['2017-01-30 23:45', '2017-01-30 20:30', '2017-01-30 18:22', '2017-01-30 05:54'],
       ['2017-01-29 17:39', '2017-01-29 15:39', '2017-01-29 14:45', '2017-01-29 11:51', '2017-01-29 11:15', '2017-01-29 09:41', '2017-01-29 03:10']
      ]
      

      【讨论】:

      • 感谢您的回答,但这不是我想要的。可能是我的错误,我不是很清楚。请看我的编辑。
      【解决方案4】:

      我正在使用字典来存储推文的日期和数量。 for 循环之后的前 2 行只是从时间戳中提取日期,我在空格上拆分时间戳并取第一部分来获取日期,然后我只是从日期中提取最后两件事。

      date_dict = {}
      for dayin timestamp_list:
        day = day.split(' ')[0]
        day = day[len(day)-2:len(day)]
        if day in date_dict.keys():
          date_dict[day] += 1
        else
          date_dict[day] = 1
      

      现在,您可以将月份和日期一起存储在 dict 中,因为它们也是键。

      【讨论】:

      • 一点也不差!不错的一个,加一个:),如果你愿意,请查看我的答案,看看另一个很酷的选择:D
      • 感谢您的回答,但是,这不是我想要的。但这可能是我的错误,我不够清楚。请看我的编辑。
      【解决方案5】:

      直方图在 matplotlib 中很容易实现:

      import matplotlib.pyplot as plt
      # generate data in list form here
      plt.hist(list)
      plt.show()
      

      您可以通过执行 plt.hist(list, bins=desired number) 来设置 bin 的数量

      我不确定 matplotlib 将如何处理日期字符串,但您可以将开始日期设置为 0,每隔一个日期设置为 x(第 0 天之后的几天)。然后您可以调整 bin 的数量,使 1 bin 对应于一天。

      【讨论】:

        猜你喜欢
        • 2020-07-31
        • 1970-01-01
        • 2018-02-05
        • 1970-01-01
        • 1970-01-01
        • 2014-04-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多