【问题标题】:How to transform a wide dataframe to plot specific data如何转换宽数据框以绘制特定数据
【发布时间】:2021-11-15 18:32:04
【问题描述】:

我有一个如下的数据框:

import pandas as pd

# sample data
# sample data
data = {'RowName': ['A1', 'A2', 'A3'], '20/09/21 (LP%)': [120, 0, 0], '20/09/21 (Vol)': [13, 1, 31], '20/09/21 (OI)': [0, 0, 0], '21/09/21 (LP%)': [135.0, 143.43, 143.43], '21/09/21 (Vol)': [68.6, 63.81, 58.1], '21/09/21 (OI)': [0, 0, 0], '22/09/21 (LP%)': [130, 0, 0], '22/09/21 (Vol)': [0, 0, 0], '22/09/21 (OI)': [75, 80, 85]}
df = pd.DataFrame(data)

# display(df)
  RowName  20/09/21 (LP%)  20/09/21 (Vol)  20/09/21 (OI)  21/09/21 (LP%)  21/09/21 (Vol)  21/09/21 (OI)  22/09/21 (LP%)  22/09/21 (Vol)  22/09/21 (OI)
0      A1             120              13              0          135.00           68.60              0             130               0             75
1      A2               0               1              0          143.43           63.81              0               0               0             80
2      A3               0              31              0          143.43           58.10              0               0               0             85

在 pandas 中使用 matplotlib 和以下数据框,有没有办法绘制:

  • x 轴:其中包含 (LP%) 的列 - 获取日期并将这些列中的每一列用作 x 轴上的一个点

    我已经使用这个选择了列:

    df2 = df.filter(regex='LP%')
    
  • y 轴:仅 A1 行的实际值

类似这样的:

【问题讨论】:

    标签: python pandas datetime matplotlib plot


    【解决方案1】:

    您需要首先重塑您的数据框。从这样的数据框开始:

      RowName  20/09/21 (LP%)  20/09/21 (Vol)  20/09/21 (OI)  21/09/21 (LP%)  21/09/21 (Vol)  21/09/21 (OI)  22/09/21 (LP%)  22/09/21 (Vol)  22/09/21 (OI)
    0      A1             120              13              0          135.00           68.60              0             130               0             75
    1      A2               0               1              0          143.43           63.81              0               0               0             80
    2      A3               0              31              0          143.43           58.10              0               0               0             85
    

    您可以通过以下方式重新塑造:

    # row filter
    df = df.iloc[:1, :]
    
    # column filter and transpose
    df = df[[col for col in df.columns if '(LP%)' in col]].T
    
    # convert column name to datetime value
    df.index = pd.to_datetime(df.index.map(lambda x: x.split(' ')[0]))
    
    # pass a sting as label
    df.columns = ['value']
    

    然后你可以简单地绘制:

    df.plot()
    
    plt.show()
    

    完整代码

    import pandas as pd
    import matplotlib.pyplot as plt
    
    
    df = pd.read_csv(r'data/data.csv')
    
    
    df = df.iloc[:1, :]
    df = df[[col for col in df.columns if '(LP%)' in col]].T
    df.index = pd.to_datetime(df.index.map(lambda x: x.split(' ')[0]))
    df.columns = ['value']
    
    df.plot()
    
    plt.show()
    


    您可以进一步自定义日期时间轴:

    import matplotlib.dates as md
    
    fig, ax = plt.subplots()
    
    ax.plot(df.index, df['value'])
    
    ax.set_xlabel('Date')
    ax.set_ylabel('LP Value')
    
    ax.xaxis.set_major_locator(md.DayLocator(interval = 1))
    ax.xaxis.set_major_formatter(md.DateFormatter('%Y-%m-%d'))
    plt.setp(ax.xaxis.get_majorticklabels(), rotation = 0)
    ax.set_xlim([df.index[0], df.index[-1]])
    
    plt.show()
    

    【讨论】:

      【解决方案2】:

      查看您的数据框(假设它被命名为df),我认为最快的方法是转置它,因为您想将行用作列:

      df_trans = df.transpose() #or df.T
      df_trans.plot.line(x='RowName', y='A1', color='red')
      import matplotlib.pyplot as plt
      plt.show() 
      

      也许您想重命名'Rowname' 列:

      df_trans.rename({0: 'LP'}, axis=1)
      df_trans.plot.line(x='LP', y='A1', color='red')
      import matplotlib.pyplot as plt
      plt.show()
      

      【讨论】:

      • 也有用,谢谢
      【解决方案3】:
      • 当前实现的问题是您只能获得'A1' 的结果,然后可能您已经重复代码以获取其他数据。
      • pandas.wide_to_long 将允许在日期之后带有存根的所有列进行转换。
        • 这要求存根位于最前面,可以通过列名的列表理解来调整。
        • suffix='\d+\/\d+\/\d+' 匹配要提取的日期格式。
      • 转换数据框后,就可以更轻松地使用和访问所有数据。
      • 使用pandas.DataFrame.pivot 重塑数据以绘制'(LP%)'
      • 直接用pandas.DataFrame.plot绘图
        • 线图x轴数据格式为%M-%D %H,因为只有少量数据。当数据天数增加时,格式会更新。
        • 索引将是 x 轴,因此无需指定 x=
        • 使用y=指定列名,或者不使用它,所有列都会被绘制出来。
      • python 3.8.11pandas 1.3.2matplotlib 3.4.3seaborn 0.11.2中测试
      import pandas as pd
      
      # sample data
      data = {'RowName': ['A1', 'A2', 'A3'], '20/09/21 (LP%)': [120, 0, 0], '20/09/21 (Vol)': [13, 1, 31], '20/09/21 (OI)': [0, 0, 0], '21/09/21 (LP%)': [135.0, 143.43, 143.43], '21/09/21 (Vol)': [68.6, 63.81, 58.1], '21/09/21 (OI)': [0, 0, 0], '22/09/21 (LP%)': [130, 0, 0], '22/09/21 (Vol)': [0, 0, 0], '22/09/21 (OI)': [75, 80, 85]}
      df = pd.DataFrame(data)
      
      # adjust the column names so the stub is before the date
      df.columns = [' '.join(col.split(' ')[::-1]) if len(col.split(' ')) > 1 else col for col in df.columns]
      
      # convert to long form
      df = pd.wide_to_long(df, stubnames=['(LP%)', '(Vol)', '(OI)'], i=['RowName'], sep=' ', j='Date', suffix='\d+\/\d+\/\d+').reset_index()
      
      # convert the Date column to a datetime dtype
      df.Date = pd.to_datetime(df.Date).dt.date
      
      # display(df.head())
        RowName        Date   (LP%)  (Vol)  (OI)
      0      A1  2021-09-20  120.00  13.00     0
      1      A2  2021-09-20    0.00   1.00     0
      2      A3  2021-09-20    0.00  31.00     0
      3      A1  2021-09-21  135.00  68.60     0
      4      A2  2021-09-21  143.43  63.81     0
      
      # pivot the LP% column
      dlp = df.pivot(index='Date', columns='RowName', values='(LP%)')
      
      # display(dlp)
      RowName        A1      A2      A3
      Date                             
      2021-09-20  120.0    0.00    0.00
      2021-09-21  135.0  143.43  143.43
      2021-09-22  130.0    0.00    0.00
      
      # plot any specific column
      dlp.plot(y=['A1'], rot=0, figsize=(10, 5), marker='o', title='LP%: A1')
      

      # or all 3
      dlp.plot(rot=0, figsize=(10, 5), marker='o', title='LP%')
      
      • 'A3' 行覆盖了'A2' 行,因为数据相同

      # specify the kind parameter for a bar plot
      dlp.plot(kind='bar', rot=0, figsize=(10, 5), title='LP%')
      

      • 再添加一个步骤并使用pandas.DataFrame.meltdf 重塑为一个完整的长格式,以便使用seaborn.relplot 轻松绘制所有数据。
        • seabornmatplotlib 的高级 API。
      import seaborn as sns
      
      # melt
      dfm = df.melt(id_vars=['RowName', 'Date'])
      
      # display(dfm.head())
        RowName        Date variable   value
      0      A1  2021-09-20    (LP%)  120.00
      1      A2  2021-09-20    (LP%)    0.00
      2      A3  2021-09-20    (LP%)    0.00
      3      A1  2021-09-21    (LP%)  135.00
      4      A2  2021-09-21    (LP%)  143.43
      
      # plot
      sns.relplot(kind='line', data=dfm, x='Date', y='value', marker='o', row='variable', hue='RowName', height=3.5, aspect=2.25)
      

      【讨论】:

      • 非常有用的特伦顿,也谢谢你
      • @Sylv99 不客气。
      猜你喜欢
      • 1970-01-01
      • 2021-12-29
      • 2021-10-20
      • 2019-07-19
      • 2021-04-02
      • 2016-09-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多