【问题标题】:Y-axis values cuts off using seaborn scatter plot使用 seaborn 散点图截断 Y 轴值
【发布时间】:2021-01-22 13:21:05
【问题描述】:

我在绘制 Y 轴值从 1 到 20+ 百万的大 CSV 文件时遇到问题。我现在面临两个问题。

  1. Y 轴并未显示它应该显示的所有值。使用原始数据时,最多显示600万,而不是显示所有数据最多2000万。在我下面放的示例数据(较小的数据)中,它只显示了第一个 Y 轴值,不显示任何其他值。

  2. 在标签部分,由于我使用的是hue和style = name,所以“name”作为标签标题和里面的一个项目出现。

问题:

  1. 谁能给我一个样本或帮助我回答如何显示所有 Y 轴值?如何修复它以显示所有 Y 值?

  2. 如何在不去除散点形状和颜色的情况下去除标签部分下的“名称”?

(请让我知道是否存在任何来源,或者此问题已在其他帖子中得到回答,但未将其标记为重复。如果我有任何需要修复的语法/拼写问题,请告诉我。谢谢!)

您可以在下面找到我用来绘制图表和示例数据的函数。

def test_graph (file_name):

    data_file = pd.read_csv(file_name, header=None, error_bad_lines=False, delimiter="|", index_col = False, dtype='unicode')
    data_file.rename(columns={0: 'name',
                              1: 'date',
                              2: 'name3',
                              3: 'name4',
                              4: 'name5',
                              5: 'ID',
                              6: 'counter'}, inplace=True)

    data_file.date = pd.to_datetime(data_file['date'], unit='s')
    
    norm = plt.Normalize(1,4)
    cmap = plt.cm.tab10

    df = pd.DataFrame(data_file)
 
    # Below creates and returns a dictionary of category-point combinations,
    # by cycling over the marker points specified.   
    points = ['o', 'v', '^', '<', '>', '8', 's', 'p', 'H', 'D', 'd', 'P', 'X']
    mult = len(df['name']) // len(points) + (len(df['name']) % len(points) > 0)
    markers = {key:value for (key, value)
               in zip(df['name'], points * mult)} ; markers
   
    sc = sns.scatterplot(data = df, x=df['date'], y=df['counter'], hue = df['name'], style = df['name'], markers = markers, s=50)
    ax.set_autoscaley_on(True)             
    
    ax.set_title("TEST", size = 12, zorder=0)      
            
    plt.legend(title="Names", loc='center left', shadow=True, edgecolor = 'grey', handletextpad = 0.1, bbox_to_anchor=(1, 0.5))             
               
    ax.xaxis.set_major_locator(ticker.MultipleLocator(1))
    ax.yaxis.set_major_locator(ticker.MultipleLocator(100))               
               
    plt.xlabel("Dates", fontsize = 12, labelpad = 7)
    plt.ylabel("Counter", fontsize = 12)
    plt.grid(axis='y', color='0.95')
    
    fig.autofmt_xdate(rotation = 30)     
              
fig = plt.figure(figsize=(20,15),dpi=100)
ax = fig.add_subplot(1,1,1)                
test_graph(file_name)

plt.savefig(graph_results + "/Test.png", dpi=100)               

# Prevents to cut-off the bottom labels (manually) => makes the bottom part bigger
plt.gcf().subplots_adjust(bottom=0.15)
plt.show()

          

样本数据

namet1|1582334815|ai1|ai1||150|101
namet1|1582392415|ai2|ai2||142|105
namet2|1582882105|pc1|pc1||1|106
namet2|1582594106|pc1|pc1||1|123
namet2|1580592505|pc1|pc1||1|141
namet2|1580909305|pc1|pc1||1|144
namet3|1581974872|ai3|ai3||140|169
namet1|1581211616|ai4|ai4||134|173
namet2|1582550907|pc1|pc1||1|179
namet2|1582608505|pc1|pc1||1|185
namet4|1581355640|ai5|ai5|bcu|180|298466
namet4|1582651641|pc2|pc2||233|298670
namet5|1582406860|ai6|ai6|bcu|179|298977
namet5|1580563661|pc2|pc2||233|299406
namet6|1581283626|qe1|q0/1|Link to btse1/3|51|299990
namet7|1581643672|ai5|ai5|bcu|180|300046
namet4|1581758842|ai6|ai6|bcu|179|300061
namet6|1581298027|qe2|q0/2|Link to btse|52|300064
namet1|1582680415|pc2|pc2||233|300461
namet6|1581744427|pc3|p90|Link to btsi3a4|55|6215663
namet6|1581730026|pc3|p90|Link to btsi3a4|55|6573348
namet6|1582190826|qe2|q0/2|Link to btse|52|6706378
namet6|1582190826|qe1|q0/1|Link to btse1/3|51|6788568
namet1|1581974815|pc2|pc2||233|6895836
namet4|1581974841|pc2|pc2||233|7874504
namet6|1582176427|qe1|q0/1|Link to btse1/3|51|9497687
namet6|1582176427|qe2|q0/2|Link to btse|52|9529133
namet7|1581974872|pc2|pc2||233|9573450
namet6|1582162027|pc3|p90|Link to btsi3a4|55|9819491
namet6|1582190826|pc3|p90|Link to btsi3a4|55|13494946
namet6|1582176427|pc3|p90|Link to btsi3a4|55|19026820

我得到的结果:

大数据:

小数据:

更新图表 Updated-graph

【问题讨论】:

    标签: python matplotlib scatter-plot


    【解决方案1】:

    首先,对您的帖子进行一些改进:您缺少导入语句

    import pandas as pd
    import matplotlib.pyplot as plt
    from matplotlib import ticker
    import seaborn as sns
    

    线

    df = pd.DataFrame(data_file)
    

    不是必需的,因为data_file 已经是一个DataFrame。线条

    points = ['o', 'v', '^', '<', '>', '8', 's', 'p', 'H', 'D', 'd', 'P', 'X']
    mult = len(df['name']) // len(points) + (len(df['name']) % len(points) > 0)
    markers = {key:value for (key, value)
               in zip(df['name'], points * mult)}
    

    不要像您期望的那样循环使用points,也许可以按照建议的here 使用itertools。此外,设置 yticks 像

    ax.yaxis.set_major_locator(ticker.MultipleLocator(100))
    

    如果您的数据跨越的值从 0 到 2000 万,每 100 可能太多,请考虑将 100 替换为 1000000。

    我能够重现您的第一个问题。使用df.dtypes,我发现counter 列存储为object 类型。添加行

    df['counter']=df['counter'].astype(int)
    

    为我解决了您的第一个问题。不过,我无法重现您的第二个问题。这是我的结果图: 您是否尝试将所有软件包更新到最新版本?


    编辑: 作为对您的评论的跟进,您还可以通过替换 1 来调整绘图中的 xticks 数量

    ax.xaxis.set_major_locator(ticker.MultipleLocator(1))
    

    更高的数字,比如 10。结合我的所有建议并删除看似不必要的函数定义,我的代码版本如下所示:

    import pandas as pd
    import matplotlib.pyplot as plt
    from matplotlib import ticker
    import seaborn as sns
    import itertools
    
    fig = plt.figure()
    ax  = fig.add_subplot()
    
    df = pd.read_csv(
        'data.csv',
        header          = None,
        error_bad_lines = False,
        delimiter       = "|",
        index_col       = False,
        dtype           = 'unicode')
    df.rename(columns={0: 'name',
                       1: 'date',
                       2: 'name3',
                       3: 'name4',
                       4: 'name5',
                       5: 'ID',
                       6: 'counter'}, inplace=True)
    
    df.date = pd.to_datetime(df['date'], unit='s')
    df['counter'] = df['counter'].astype(int)
    
    points  = ['o', 'v', '^', '<', '>', '8', 's', 'p', 'H', 'D', 'd', 'P', 'X']
    markers = itertools.cycle(points) 
    markers = list(itertools.islice(markers, len(df['name'].unique())))
    
    sc = sns.scatterplot(
        data    = df,
        x       = 'date',
        y       = 'counter',
        hue     = 'name',
        style   = 'name',
        markers = markers,
        s       = 50)           
    
    ax.set_title("TEST", size = 12, zorder=0)             
    ax.legend(
        title          = "Names",
        loc            = 'center left',
        shadow         = True,
        edgecolor      = 'grey',
        handletextpad  = 0.1,
        bbox_to_anchor = (1, 0.5))             
               
    ax.xaxis.set_major_locator(ticker.MultipleLocator(10))
    ax.yaxis.set_major_locator(ticker.MultipleLocator(1000000))             
    ax.minorticks_off()
          
    ax.set_xlabel("Dates", fontsize = 12, labelpad = 7)
    ax.set_ylabel("Counter", fontsize = 12)
    ax.grid(axis='y', color='0.95')
    
    fig.autofmt_xdate(rotation = 30)  
    plt.gcf().subplots_adjust(bottom=0.15)   
    plt.show()
    

    【讨论】:

    • 非常感谢您的回答。感谢您的时间和帮助。抱歉,我的原始文档中有导入,只是忘了把它们放进去。谢谢你提到它们。应用您提到的更改后(除了标记),我收到了正确的 Y 值(如图所示为 10^7。现在出现的问题是 X 轴值重叠,因为它们太多了,而且在 X 轴上创建一个黑色标记。请参阅上面的更新图表以供参考。我该如何解决该问题?能否请您也粘贴您生成的代码以供参考?再次感谢!
    • 如果我的回复解决了您的问题,请将其标记为已接受的答案。
    • 你好@Alperino。你的回复对我帮助很大。 x 轴看起来不错,但不知何故,它显示的日期早在 2000 年代。我认为 DateTime 可能存在问题,但不确定。根据我的数据,转换时日期必须是 2021 年。转换是正确的,但我认为在绘图时,它会将其视为一般的 DateTime 或我不理解的东西。你知道什么可能导致这个问题吗?知道我该如何解决吗?再次感谢您的支持和时间!
    • 有太多可能的原因导致无法在评论中解决。此外,我们现在正在讨论超出您最初要求的问题。我建议您设置一个最小的工作示例,包括导致问题的数据并打开一个新的单独帖子。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-10
    • 1970-01-01
    • 1970-01-01
    • 2020-09-28
    • 2023-03-04
    • 2022-01-18
    相关资源
    最近更新 更多