【问题标题】:Double labels on Y-axis MatplotlibY 轴 Matplotlib 上的双标签
【发布时间】:2019-09-03 11:07:48
【问题描述】:

我制作了一个顶部带有散点图的条形图。数据大约是 100 本书,出版日期以及作者出生和死亡的年份。 barh 显示作者在世的时间,散点图显示出版书籍的年份。

我面临的问题是能够在一个栏上绘制多本书。因为我现在有不同的书重复栏。我正在根据数组中的位置创建 y 轴,稍后我将添加标签。

我的相关代码:

# dataframe columns to arrays. (dataset is my pandas dataframe)
begin = np.array(dataset.BORN)
end = np.array(dataset.DIED)
book = np.array(dataset['YEAR (BOOK)'])

# Data to a barh graph (sideways bar)
plt.barh(range(len(begin)), end-begin, left=begin, zorder=2, 
color='#007acc', alpha=0.8, linewidth=5)

# Plots the books in a scatterplot. Changes marker color and shape.
plt.scatter(book, range(len(begin)), color='purple', s=30, marker='D', zorder=3)

# Sets the titles of the y-axis.
plt.yticks(range(len(begin)), dataset.AUTHOR)

# Sets start and end of the x-axis.
plt.xlim([1835, 2019])

# Shows the plt
plt.show()

显示我当前图表的一部分的图片:

【问题讨论】:

  • 你希望情节是什么样的?例如作者可以只出现一次(在一行上)并拥有多颗钻石(每本出版的书一颗)。还是别的什么?
  • 这确实是我想要的。每个作者一个栏,如果有多本书,则有多个菱形。

标签: python matplotlib


【解决方案1】:

我会汇总您的数据集,以便您使用 groupby 每行获得一个作者并使用它来绘制条形图,然后将其加入以获得用于绘制书籍的值,例如:

import pandas as pd
import matplotlib.pyplot as plt

df = pd.DataFrame([
    ['foo', 1950, 1990, 1980],
    ['foo', 1950, 1990, 1985],
    ['bar', 1930, 2000, 1970],
], columns=['author', 'born', 'died', 'published'])

拉入包并创建一个虚拟数据集,接下来我们将其减少到每个作者一行,获取他们出生和死亡的时间:

agg = df.groupby('author')['born', 'died'].agg(min).reset_index()
agg['auth_num'] = range(len(agg))

reset_index 使author 回到普通列,我们创建了一个任意的auth_num 列,如果您想按作者以外的其他内容对作者进行排序,您可能需要在其中放置一个sort_values名称(我建议通常按字母顺序排列isn't the most useful

接下来,我们可以将其加入原始数据集,以获取每本书的作者编号:

df2 = pd.merge(df, agg[['author', 'auth_num']], on='author')

最后画出来:

plt.barh(agg.auth_num, agg.died - agg.born, left=agg.born, zorder=-1, alpha=0.5)
plt.yticks(agg.auth_num, agg.author)

plt.scatter(df2.published, df2.auth_num)

给出类似的东西:

注意:如果在调用barh 之前将use_sticky_edges 设置为False,它将允许x 轴自动缩放,因此最左边的作者不会“粘”在左边-手边距

【讨论】:

    【解决方案2】:

    当然,您可以使用多种选项。 您可以为第一、第二、第三本书创建另一个数组。或者您可以创建一个字典或数组列表来绘制每个作者的书籍。

    我使用下面的虚拟数据重新生成了一些示例。

    import matplotlib.pyplot as plt
    import numpy as np
    
    fig,axs = plt.subplots(1,1,figsize=(10,10))
    
    # dataframe columns to arrays. (dataset is my pandas dataframe)
    begin = np.arange(1900,1950)
    end = np.arange(1975,2025)
    
    # create two random arrays for your book dates
    book1 = np.array(np.random.randint(low=1950, high=1970, size=50))
    book2 = np.array(np.random.randint(low=1950, high=1970, size=50))
    
    # add some athor names
    author_names = [f'Author_{x+1}' for x in range(50)]
    
    # Data to a barh graph (sideways bar)
    axs.barh(range(len(begin)), end-begin, left=begin, zorder=2, 
    color='#007acc', alpha=0.8, linewidth=5)
    
    # Plots the books in a scatterplot. Changes marker color and shape.
    axs.scatter(book1, range(len(begin)), color='purple', s=30, marker='D', zorder=3, label='1st Book')
    
    # second array of books
    axs.scatter(book2, range(len(begin)), color='yellow', s=30, marker='D', zorder=3, label='2nd Book')
    
    # or plot a custom array of books
    # you could do this in a for loop for all authors
    axs.scatter(x=[1980,2005], y=[10,45], color='red', s=50, marker='X', zorder=3, label='3rd Book')
    
    # Sets the titles of the y-axis.
    axs.set_yticks(range(len(begin)))
    axs.set_yticklabels(author_names)
    
    # Add legend
    axs.legend()
    
    # Sets start and end of the x-axis.
    axs.set_xlim([1895, 2025])
    axs.set_ylim([-1,50]);
    

    【讨论】:

      【解决方案3】:

      (下次请包含数据框示例!)

      我会使用很棒的numpy.unique 方法来执行分组操作。

      import numpy as np
      import pandas as pd
      import matplotlib.pyplot as plt
      
      
      dataset = pd.DataFrame({'BORN': [1900, 1920, 1900],
                              'DIED': [1980, 1978, 1980],
                              'AUTHOR': ['foo', 'bar', 'foo'],
                              'YEAR (BOOK)': [1950, 1972, 1961]})
      
      # --group by author
      unique_authors, index, reverse_index = np.unique(dataset.AUTHOR.values, return_index=True, return_inverse=True)
      authors_df = dataset.loc[index, ['AUTHOR', 'BORN', 'DIED']]
      dataset['AUTHOR_IDX'] = reverse_index  # remember the index
      
      # dataframe columns to arrays.
      begin = authors_df.BORN.values
      end = authors_df.DIED.values
      authors = authors_df.AUTHOR.values
      
      # --Author data to a barh graph (sideways bar)
      plt.barh(range(len(begin)), end-begin, left=begin, zorder=2, color='#007acc', alpha=0.8, linewidth=5)
      
      # Sets the titles of the y-axis.
      plt.yticks(range(len(begin)), authors)
      
      # Sets start and end of the x-axis.
      plt.xlim([1835, 2019])
      
      # --Overlay book information
      # dataframe columns to arrays
      book = dataset['YEAR (BOOK)'].values
      
      # Plots the books in a scatterplot. Changes marker color and shape.
      plt.scatter(book, reverse_index, color='purple', s=30, marker='D', zorder=3)
      
      # Shows the plt
      plt.show()
      

      产量:

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-05-11
        • 2020-06-22
        • 2023-03-04
        • 1970-01-01
        • 2013-01-23
        • 1970-01-01
        • 2012-03-14
        相关资源
        最近更新 更多