【问题标题】:Plot n graphs and save them in n different files绘制 n 个图形并将它们保存在 n 个不同的文件中
【发布时间】:2021-10-20 23:07:26
【问题描述】:

首先,我想明确一点,我不是 Python 专家,但仍在学习如何使用 pandas。我翻阅了较旧的帖子,但找不到合适的答案。

我一直在尝试编写 92 份合约的数据分析代码。对于它们中的每一个,我想绘制一个特定的分析(每次获取相同数据帧的一些列)并将每个分析保存在不同的文件夹中(分析 1、分析 2、...)。

到目前为止,我面临着许多困难。因此,在关注要绘制的内容之前,我想了解如何编写每次将每个绘图保存在不同的 .png 文件中的代码。我尝试过的代码似乎没有保存任何内容,因为当我转到文件夹时它是空的。

感谢 waykiki 的帮助,我已经能够更新我的代码。现在我知道如何创建与我生成的分析一样多的文件夹。然而,我似乎不明白如何对每次分析的 92 个图的绘图进行编码。我的代码现在看起来像这样:

import pandas as pd
import matplotlib.pyplot as plt
import os

# Folder in which I want the analyses to be saved
URL5 = r"C:\Users\A\AppData\Local\Programs\Python\Python39"
# 1 graph per ID_Contrat (thus, 92 graphs)
groups = outer_merged_df.groupby("ID_Contrat") #where outer_merged_df is my dataframe
# How to name each plot.
List_ID_Contrat = outer_merged_df["ID_Contrat"].tolist()

def create_plot(file_name, x, y):
    # Create your plot. It is my understanding that here I should just give the x and the y I want to plot.
    fig = plt.figure()
    plt.plot(x, y, color = "red", kind = "line", legend = "true", linewidth = 2)
    plt.savefig(file_name)
    plt.show()

def main():
    # must be full-path. 
    parent_folder = URL5
    # move to parent directory
    os.chdir(parent_folder)
    # I want file_name to be different for each graph
    extension = ".png"
    # 5 = how many analyses I want to do
    for i in range(5):
        for name in List_ID_Contrat :
            file_name = "Analyse" + str[i+1] "{}" + extension.format(name) # I want file_name to be different for each graph and looking like "Analyse i Contrat XX"
        # Create a new folder
        folder_name = 'Analysis ' + str(i+1)
        os.mkdir(folder_name)
        full_file_name = folder_name + '/' + file_name
        x = np.linspace(1,100,100)
        y = np.random.random(100)
        create_plot(full_file_name, x, y)
        print("plot "+ savefile +" finished".format(name))
        
if __name__ == "__main__":
    main()

然而,当我运行我的代码时,它不再绘制 92 个图,也不想再创建文件夹(尽管它确实使用了 Waykiki 的方法)。在第一轮中 for 循环被打破(我只得到文件夹“分析 1”) 我收到错误消息:

AttributeError: 'Line2D' object has no property 'kind'

您能解释一下如何保存这些图表吗?我迷路了..

谢谢

【问题讨论】:

  • 您好!我看不到您在哪里绘制图表。如果使用 matplotlib.pyplot 作为 plt 或 pd.plot(x,y) 如果使用 pandas 作为 pd,你应该有类似 plt.plot(x,y) 的东西。
  • 您好,您是对的!我忘记了我的代码的某些部分......因此我编辑了我的帖子! :)
  • 您没有提供可重现的示例。我可以给你一个简单的例子来说明如何现在做,或者你可以提供最小的可重复的例子。
  • 好的,让我更新我的帖子,以便我们有共同点。非常感谢!

标签: python loops matplotlib savefig


【解决方案1】:

我认为您的方法是正确的,因为您将问题分为两个步骤:

1.) 完成技术细节(创建、组织和浏览文件夹和数据)。

2.) 实际创建/绘制地块。

这是一个简单的原型脚本。该脚本在主目录 '/home/user/my_analysis/' 中创建了 N 个子文件夹。所有子文件夹都命名为“AnalysisX”,其中 X 是文件夹的编号。

每个文件夹都包含不同的情节。

注意:我的文件夹路径适用于 linux 机器,所以请记住 '/home/user/some_folder/' 在 Windows 中不是有效路径! (我知道您已经掌握了这部分内容,但它可能对其他用户有用)。

import os
import numpy as np
import matplotlib.pyplot as plt


def create_plot(file_name, x, y):
    # Create your plot
    fig = plt.figure()
    plt.plot(x, y, color='red', linewidth=2)
    plt.savefig(file_name)
    plt.show()


def main():
    # must be full-path
    parent_folder = '/home/user/my_analysis/'

    # move to parent directory
    os.chdir(parent_folder)

    file_name = 'plot'
    extension = '.png'
    for i in range(5):
        # Create a new folder
        folder_name = 'Analysis' + str(i+1)
        os.mkdir(folder_name)

        full_file_name = folder_name + '/' + file_name + extension
        x = np.linspace(1, 100, 100)
        y = np.random.random(100)
        create_plot(full_file_name, x, y)


if __name__ == '__main__':
    main()

为清楚起见,这就是文件夹结构的样子。我只审查了我的真实用户名:

【讨论】:

  • 非常感谢!它工作得很好!现在,因为我想绘制 92 个不同的图表(每个合约 1 个),我试图编辑代码,但似乎有一个错误.. 让我更新我的帖子
  • 实际上,我尝试修改您的代码,以便程序了解现在,对于我想要的每个分析:1) 与合同一样多的图表 2) 每个分析都不同我一直在尝试替代我的代码,但如果你有一个想法,你能告诉我吗?
  • / 在 Windows 中是不允许的。也许这就是原因?
  • 嘿,Karina,我的麻烦是:我的代码不明白我想要 92 个图表,这些图表的数据应该来自数据框的某些列,并且我不希望它们中的每一个都以 a 的元素命名列表(我从数据框创建的列表)
  • 极光没有问题!我查看了您提供给我们的更新代码,以及您复制的错误。 @Karina 似乎已经回答了这个问题——目前的错误是你混合了两种绘图风格。 plt.plot(...) 是一个 matplotlib 函数。此函数不接受名为“kind”的参数。删除它,然后尝试在没有它的情况下运行代码。
【解决方案2】:

您仍然没有提供 DataFrame 作为示例。我无权访问您的本地文件夹。无论如何,我假设你有 pandas DataFrame,所以我为随机数据编写代码。在给你代码之前,我会尝试澄清一些误解:

1.引用您的评论:

# 创建你的情节。我的理解是,在这里我应该只给出我想要绘制的 x 和 y。 是的,这是正确的。但是,您将 pandas 绘图和 matplotlib 混为一谈:

plt.plot(x, y, color = "red", kind = "line", legend = "true", linewidth = 2)

坚持一个。 kind='line', legend = 'true' 是 pandas 绘图,而 plt.plot() 是 matplotlib 绘图。混合它是行不通的;)

2。 extension = '.png' 不是必需的(至少在这种情况下)

plt.savefig() 无论如何都会给你.png。我没有尝试过,但我想如果您将.png 添加为文件名,它甚至可能会导致其他问题。

这是我的代码:

def create_plot(file_name, x, y):
    fig, ax = plt.subplots()
    ax.plot(x, y, 'r', linewidth = 2)
    plt.savefig(file_name)
    plt.close()

def createalotofdata(n, df):
    for i in range(n):
        df[f'data number{i}'] = np.random.rand(10)
#     print(df)

x = np.arange(10)
df = pd.DataFrame({'x0': x})

createalotofdata(5, df)

for i in range(len(list(df))-1):
    create_plot(f'Plot number {i}', df['x0'], df[f'data number{i}'])

所以输出什么都看不到,只有绘图被保存:

希望您能理解并根据您的需要进行调整。如果还有什么不清楚的地方,请再次询问。

【讨论】:

  • 您好,Karina,非常感谢您的解释。你是对的,我没有提供数据框......我的脑海里闪过。我一直在混合什么是 matplot 库和什么是 pandas':我应该使用哪种绘图:您似乎使用 myplotlib 进行编码,是因为它更直观吗?更轻松 ?有什么具体原因吗?扩展没有产生任何额外的错误信息,但感谢您的建议! :)
  • 我昨天花时间编写我想要的代码,我终于成功了!您的解释和代码对我有很大帮助。我会回复我自己的帖子,以便其他用户找到出路:)。另外,你能告诉我你的想法吗?我还是个初学者,我认为有些事情我可以做得不那么复杂..
  • 欢迎您!至于你的问题:matplotlib.pyplot 只是我个人的喜好,我觉得它更容易理解和修改。此外,它在绘图方面比 pandas 做得更多,这是有原因的,它是一个绘图库,而另一个更多是用于数据帧。
  • 感谢您的回答!你是对的,显然这个 matplotlib 库不是白白创建的!我会继续:我现在需要告诉我的程序来绘制不同的分析! :)
【解决方案3】:

所以昨天我发布了这个问题:如何为不同的分析绘制 n 个图,并将它们保存在不同的 .png 文件中?感谢 Karina 和 Waykiki(以及我自己),我成功了! 下面是我现在拥有的代码 - 实际有效 - 带有一个示例。

我用一个简单的数据框创建了一个简单的例子:

import os
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

df = pd.DataFrame({'ID':['A','B','B','A','C','C'], 'X': [5,3,4,2,5,3], 'Y':[1,2,6,4,5,2]}) #simple dataframe

def create_plot(file_name, x, y):
    # Create your plot
    plt.plot(x, y, color='red', linewidth=2, label = ID) # As I was advised, I stoped using "group.plot" which is a function from pandas plotting library : stick to one library !
    plt.savefig(file_name)
    plt.show()

def main():
    # must be full-path
    parent_folder = r"C:\Users\A\AppData\Local\Programs\Python\Python39\Test"
    
    # move to parent directory
    os.chdir(parent_folder)

    extension = '.png'
    for i in range(5):
        # Create a new folder
        folder_name = 'Analysis' + str(i+1)
        file_name = 'Analysis' + str(i+1)
        #print(type(file_name))
        os.mkdir(folder_name)
        for ID in df.ID.unique():
        #for ID, group in groups:
            df1 = df[df.ID == ID]
            file_name = "Analysis " + str(i+1) +" - {}".format(ID)
            print(file_name)
            full_file_name = folder_name + '/' + file_name + extension
            x = df1.X
            y = df1.Y
            create_plot(full_file_name, x, y)
if __name__ == '__main__':
    main()

此代码有效。我现在可以:

  1. 使用 create_plot() 函数绘制图形
  2. 每次分析创建 1 个文件夹(此处为 5 个分析)
  3. 将每个图保存到 .png 文件中,该文件的名称在“file_name”中定义(即 Analysis 1 - C(在 Analysis1 文件夹中)、Analysis 2 - A(在 Analysis2 文件夹中...)

现在我需要编码的是:

  1. 如何告诉我的代码对于分析 1 我想要我的 df 的一些列,对于分析 2 一些其他列,依此类推
  2. 更改 x_axis 标签,使其显示我定义的日期。

希望这对社区有所帮助!

【讨论】:

  • 你需要关闭这些地块……想象一下,有 92 个地块全部打开(除非你故意让它这样)。你肯定会因为一次打开 20 多个图形而触发 matplotlib 警告。顺便说一句,只是一个提示(可能不一定很重要),如果您只有 file_namestr(i+1) 来区分每个文件,那么当您运行您的再次编码以生成新图。
  • 我在开头编写了以下代码,因此它不显示 92*4 = 368 个图形 %matplotlib agg %matplotlib agg
  • 我的文件名如下: 分析 3 - Name_of_the_contract 与我的代码如果我想再次运行它,我首先需要删除所有文件夹。我相信现在没关系:我可以将它们保存在其他地方并重新启动我的程序
  • 我只是有一种感觉,这些情节将相互重叠,而不是每个情节一个。我的意思是您将第二个情节添加到第一个情节中,而不是新情节。你检查你的 .png 文件了吗?每个人一个吗?如果是,那么对不起,我的错。我不得不承认我不知道%matplotlib agg 做了什么。
  • 每个情节都不同 :) 我读到它会阻止数字显示
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-24
  • 1970-01-01
相关资源
最近更新 更多