【问题标题】:Extracting month day from datetime column to plot a seasonal line chart with Seaborn从日期时间列中提取月份日期以使用 Seaborn 绘制季节性折线图
【发布时间】:2020-01-13 16:34:36
【问题描述】:

我正在处理的数据框示例如下。

df_sub = pd.DataFrame([[2020-01-01, 2019-01-02, 2018-01-15, 2017-01-18], [2019, 2018, 2017, 2016], [15, 9, 39, 20]], columns=['GAME_DATE', 'SEASON', 'PTS')

  • 每个赛季中的 GAME_DATE 和 POINTS 大约有 20-30 个数据点。这将根据从其他数据帧 DF 中选择的内容而有所不同
  • GAME_DATE 是一个日期时间列

我想创建一个单独的情节,其中 x 轴为 game_date,y 轴为点,每个季节绘制一条线。

尝试了以下方法,但没有达到我想要的效果,因为它按顺序绘制了每个季节的数据,并在休息时有间隙。我希望每个季节都绘制在不同的线上,同时使用一年的一致 x 轴,而不是每年延伸。

ax = sns.lineplot(x = 'GAME_DATE', y = 'PTS', hue = 'SEASON', markers = True, dashes = False, data = df_sub)

认为我需要从 GAME_DATE 中提取 X-AXIS 的月份和日期,因为 SEASON 已经处理了年份/季节性组件

df_sub['SEASONAL'] = df_sub['GAME_DATE'].dt.strftime('%m-%d')

这在提取月份和日期方面起到了作用,但是当使用以下内容进行绘图时 - 创建的情节绝对是一团糟

ax = sns.lineplot(x = 'SEASONAL', y = 'PTS', hue = 'SEASON', markers = True, dashes = False, data = df_sub)

认为我需要将 df_sub['SEASONAL'] 从当前类型转换为日期时间列作为非空对象?但是,尝试以下方法会在季节性列的每个条目中插入一年(1900 年..uhhh)

df_sub['SEASONAL'] = pd.to_datetime(df_sub['SEASONAL'], format = "%m-%d")

感谢任何帮助

【问题讨论】:

    标签: python pandas seaborn


    【解决方案1】:

    绘图时字符串日期时间不起作用。您可以将字符串日期时间转换为以毫秒为单位的纪元时间。

    import pandas as pd
    import seaborn as sns; sns.set()
    import matplotlib.pylab as plt
    
    # make epoch datetime
    list_date = ['2020-01-01', '2019-01-02', '2018-01-15', '2017-01-18']
    dates = [pd.to_datetime(d) for d in list_date]
    dates_epoch = [(t- pd.Timestamp("1970-01-01")) // pd.Timedelta('1ms') for t in dates]
    
    # create dataframe
    df_sub = pd.DataFrame([dates_epoch, 
                           [2019, 2018, 2017, 2016], 
                           [15, 9, 39, 20]
                          ])
    df_sub = df_sub.T
    df_sub.columns=['GAME_DATE', 'SEASON', 'PTS']
    
    # print(df_sub)
    #        GAME_DATE  SEASON  PTS
    # 0  1577836800000    2019   15
    # 1  1546387200000    2018    9
    # 2  1515974400000    2017   39
    # 3  1484697600000    2016   20
    
    sns.lmplot(x='GAME_DATE', y='PTS', hue= 'SEASON', data=df_sub,lowess=True)
    
    # get current axis
    ax = plt.gca()
    # get current xtick labels
    xticks = ax.get_xticks()
    # convert all xtick labels to selected format from ms timestamp
    ax.set_xticklabels([pd.to_datetime(tm, unit='ms').strftime('%Y-%m-%d') for tm in xticks], rotation=50)
    
    plt.show()
    

    我不确定这是您想要的结果,但希望对您有所帮助。


    编辑回答cmets...

    对于你的情况,

    pd.to_datetime(df_sub['SEASONAL'].iloc[0], unit='ms').strftime('%m-%d')

    会起作用。

    pd.to_datetime() 使用 pandas 制作时间戳。我认为这种方式对于轻松管理时间数据很有用。

    # put some timedata, mostly string but int with unit is ok
    pd.to_datetime(1577836800000, unit='ms')
    # Timestamp('2020-01-01 00:00:00')
    pd.to_datetime('2020-01-01')
    # Timestamp('2020-01-01 00:00:00')
    

    并使用strftime(format),将时间戳从字符串转换为格式。

    pd.to_datetime('2020-01-01').strftime('%m-%d')
    # '01-01'
    

    【讨论】:

    • 感谢您的反馈,尽管这并没有达到我想要的结果。我认为我的问题在于 df_sub 数据框中的 GAME_DATE 系列列是一个字符串,就像你说的那样,这会导致绘图问题。 df_sub['SEASONAL'] = df['GAME_DATE'].dt.strftime('%m-%d') df_sub['SEASONAL'] = pd.to_datetime(df_sub['SEASONAL'], format = %m-%d') 转换为日期时间(有助于绘图?)但是这会将 1900 年添加到每个值,但我没有在格式中包含 %Y?
    • 我已在回答帖子中添加。请尝试。
    • 再次感谢,我尝试了以下df_sub['SEASONAL'] = pd.to_datetime(df['GAME_DATE']).strftime('%m-%d') 收到以下错误——系列对象没有属性strftime。然后尝试df_sub['SEASONAL'] = pd.to_datetime(player['GAME_DATE'].iloc(0), unit = 'ms').strftime('%m-%d') 收到以下错误 - 参数“值”的类型不正确(预期为 numpy.ndarray,得到 _iLocIndexer)
    • iloc[0],不是 (0)
    • 对我的疏忽深表歉意。已应用以下pd.to_datetime(df_sub['SEASONAL'].iloc[0], unit='ms').strftime('%m-%d') 格式看起来不错,但是 df_sub 中 SEASONAL 列中的第一行值随后在后续行中重复。尽管df_sub['SEASONAL'] = df_sub['GAME_DATE'].dt.strftime('%m-%d') 使用它我没有这个问题但是回到它在应用df_sub['SEASONAL'] = pd.to_datetime(df_sub['SEASONAL'], format='%m-%d') 时将1900 年添加到每个日期的问题
    猜你喜欢
    • 2019-01-07
    • 2016-08-30
    • 2020-06-02
    • 2019-03-20
    • 1970-01-01
    • 2022-06-18
    • 1970-01-01
    • 1970-01-01
    • 2017-04-05
    相关资源
    最近更新 更多