绘制目录中的所有数据文件

时间:2013-04-17 17:22:23

标签: python numpy matplotlib

我正在尝试将所有数据文件绘制在python中的目录中,然后保存生成的图。我试图编写高效的python代码(不幸的是):现在只对绘制数据感兴趣。

我是python的新手,我的目标是在我的论文中组织数字。

所以使用下面的代码,这就是我想要做的:

  1. 我列出了.dat
  2. 的所有glob个文件
  3. 我使用文件名
  4. 填充数组
  5. 我遍历此文件名数组和plot_surface每个数据文件
  6. 我尝试绘制的数据是here

    向我吐出的错误是:

    错误

      File "/home/dnaneet/Research/test_collection/dftdata/profile2.py", line 59, in <module>
        plot(x, y, z)
      File "/usr/lib/pymodules/python2.7/matplotlib/pyplot.py", line 2286, in plot
        ret = ax.plot(*args, **kwargs)
      File "/usr/lib/pymodules/python2.7/matplotlib/axes.py", line 3783, in plot
        for line in self._get_lines(*args, **kwargs):
      File "/usr/lib/pymodules/python2.7/matplotlib/axes.py", line 317, in _grab_next_args
        for seg in self._plot_args(remaining, kwargs):
      File "/usr/lib/pymodules/python2.7/matplotlib/axes.py", line 278, in _plot_args
        raise ValueError, 'third arg must be a format string'
    ValueError: third arg must be a format string
    

    Python代码

    import os
    import glob
    import sys
    import subprocess
    import matplotlib.pyplot as plt
    from mpl_toolkits.mplot3d import Axes3D
    import numpy as np
    
    from numpy import *
    from numpy.random import rand
    from pylab import pcolor, show, colorbar, xticks, yticks
    from pylab import *
    
    print 'Listing all profile/dat files'
    profilefilelist = glob.glob('*profile*.dat')
    raw_input('Press ENTER to continue...')
    print profilefilelist
    
    
    for i in profilefilelist:
      DATA = i
      def get_data(fname=DATA):
        '''Read 2d array of z coordinates from file. Convert to float values
        and wrap in a numpy array.'''
        with open(fname) as f:
            data = [map(float, line.split()) for line in f]
        return np.array(data)
        def plot(x, y, z):
    
            fig = plt.figure()
            ax = fig.gca(projection='3d')
            ax.plot_surface(x, y, z, rstride=5, cstride=5,cmap="binary",linewidth=0.1)
            ax.set_zlim3d(0.0,4.0)  
            ax.set_xlabel('X',fontsize=16,fontweight="bold")
            ax.set_ylabel('Y',fontsize=16,fontweight="bold")
            ax.set_zlabel('h(X,T)',fontsize=16,fontweight="bold")
            savefig(os.getcwd()+DATA+'.pdf',figsize=(5,5),dpi=600)
            savefig(os.getcwd()+DATA+'.pdf',figsize=(5,5),dpi=600)
    
    
    
    
    if __name__ == '__main__':
        z = get_data()
        x = range(z.shape[0])
        y = range(z.shape[1])
        x, y = np.meshgrid(x, y)
        plot(x, y, z)
    

    问题

    这是因为我的压痕不好还是在这里发生了更加险恶的事情?我该怎么做才能纠正这些错误?

    我不太了解python,并一直试图摆脱mathematica(因为我将毕业,再也买不起世界上的mathematicas或matlabs)。

    SE上提供的先前代码:

    HERE

    修改后的代码(基于答案)

    import os
    import glob
    import sys
    import subprocess
    import matplotlib.pyplot as plt
    from mpl_toolkits.mplot3d import Axes3D
    import numpy as np
    
    from numpy import *
    from numpy.random import rand
    from pylab import pcolor, show, colorbar, xticks, yticks
    from pylab import *
    
    print 'Listing all profile/dat files'
    profilefilelist = glob.glob('*profile*.dat')
    raw_input('Press ENTER to continue...')
    print profilefilelist
    DATA=profilefilelist
    
    
    for i in DATA:
        def get_data(fname=i):
            '''Read 2d array of z coordinates from file. Convert to float values
            and wrap in a numpy array.'''
            with open(fname) as f:
                data = [map(float, line.split()) for line in f]
                return np.array(data)
    for i in DATA:    
        def my_plot(x, y, z):
            fig = plt.figure()
            ax = fig.gca(projection='3d')
            ax.plot_surface(x, y, z, rstride=5, cstride=5,cmap="binary",linewidth=0.1)
            ax.set_zlim3d(0.0,4.0)  
            ax.set_xlabel('X',fontsize=16,fontweight="bold")
            ax.set_ylabel('Y',fontsize=16,fontweight="bold")
            ax.set_zlabel('h(X,T)',fontsize=16,fontweight="bold")
            plt.show()
    #        savefig(os.getcwd()+DATA+'.pdf',figsize=(5,5),dpi=600)
    #        savefig(os.getcwd()+DATA+'.pdf',figsize=(5,5),dpi=600)    
    
    
    
    if __name__ == '__main__':
                z = get_data()
                x = range(z.shape[0])
                y = range(z.shape[1])
                x, y = np.meshgrid(x, y)
                my_plot(x, y, z)
    

4 个答案:

答案 0 :(得分:2)

至少有一个缩进问题我可以看到(虽然我没有所有的依赖关系来重现这个)。

您的def图(x,y,z)位于def get_data函数内(位于for循环内)。

你只需要定义一次你的函数,这样你就可以将def get_data和def绘制线从第0列开始。然后你的

if __name__ == '__main__'

块将调用您的绘图函数而不是pyplot(如回溯中所示)。

同样,您只需要使用您正在寻找的DATA文件调用它,而不是在for循环中定义get_data。

答案 1 :(得分:2)

一些清理建议(你的任务很简单,我认为有一些不必要的操作):

  • 不要迭代列表的索引,迭代列表本身;
  • 删除样板代码(打印,raw_input仅用于确认等)
  • 利用数组创建例程。
  • 不要创建仅在一个地方调用的函数。
  • 避免多次导入,或from module import *,因为它已导致名称冲突。

以下是您的程序的修改版本,我相信它可以实现相同的结果。它不是您的问题的解决方案,而是一系列小改进(或我认为是改进):

import os
import glob
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np

for fname in glob.glob('*profile*.dat'):

    z = numpy.loadtxt(fname)

    x,y = np.meshgrid(range(z.shape[0]), range(z.shape[1]))

    fig = plt.figure()

    ax = fig.gca(projection='3d')
    ax.plot_surface(x, y, z, rstride=5, cstride=5,cmap="binary",linewidth=0.1)
    ax.set_zlim3d(0.0,4.0)

    ax.set_xlabel('X',fontsize=16,fontweight="bold")
    ax.set_ylabel('Y',fontsize=16,fontweight="bold")
    ax.set_zlabel('h(X,T)',fontsize=16,fontweight="bold")
    plt.savefig(os.getcwd()+fname+'.pdf',figsize=(5,5),dpi=600)
    plt.savefig(os.getcwd()+fname+'.pdf',figsize=(5,5),dpi=600)

您可以选择使用最后两行:

plt.savefig(os.path.join(os.getcwd, "%s.pdf" % fname), figsize=(5,5), dpi=600)

答案 2 :(得分:1)

您已经定义了自己的函数并将其命名为plot,但是当您调用plot(x,y,z)时,它看起来正在调用标准pyplot.plot命令(请参阅回溯中的代码位置) )。请尝试将其重命名为my_plot

一般而言,在这种情况下,强烈建议不要使用其他常用函数的名称来命名自己的对象(函数和变量)。

正如@tstone所说,你的函数定义在循环内部,在运行循环之前定义它们,但也给它们唯一的名称。使用唯一名称,如果您愿意,您仍然可以使用普通的plot函数,并且您已经捕获了作用域错误(它在循环中定义)因为唯一名称({{ 1}},例如)本来是未定义的。

尝试重构您的脚本:

my_plot

请注意,我更改了import ... def get_data(fname): #fname is now a required argument, to be fed in by the loop in __main__ body '''Read 2d array of z coordinates from file. Convert to float values and wrap in a numpy array.''' ... # should pass DATA to the savefig: def my_plot(x, y, z, DATA): ... savefig(...DATA...) # do everything else here: if __name__ == '__main__': print 'Listing all profile/dat files' profilefilelist = glob.glob('*profile*.dat') raw_input('Press ENTER to continue...') print profilefilelist # you didn't need `i` since you just immediately assigned it to DATA, just call it DATA in the first place for DATA in profilefilelist: z = get_data(DATA) x = range(z.shape[0]) y = range(z.shape[1]) x, y = np.meshgrid(x, y) my_plot(x, y, z, DATA) # Here, pass DATA to `my_plot` 的参数,以便它没有默认参数,但它会接受一个变量(此处称为get_data来自循环)。

答案 3 :(得分:1)

一个简单的例子,可以帮助您了解函数和循环的工作原理。

# Here I define bar 10 times, but call it 1 times
# This is what you're doing in your code
print "defining bar 10 times"
for i in range(10):
    def bar(i):
        print "bar " + str(i)
print "running it once"
bar(99)

# Here I define foo once, and call it 10 times
# This is what I think you're trying to do
print "defining foo once"
def foo(i):
    print "foo " + str(i)

print "running foo 10 times"
for i in range(10):
    foo(i)

这是上述代码的输出:

defining bar 10 times
running it once
bar 99
defining foo once
running foo 10 times
foo 0
foo 1
foo 2
foo 3
foo 4
foo 5
foo 6
foo 7
foo 8
foo 9