3

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

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

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

  1. 我列出所有.dat文件glob
  2. 我用文件名填充一个数组
  3. 我遍历这个文件名数组和plot_surface每个数据文件

我试图绘制的数据在这里

向我吐出的错误是:

错误

  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上提供的先前代码:

这里

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

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

4 回答 4

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)
于 2013-04-17T17:58:47.317 回答
2

我至少可以看到一个缩进问题(尽管我没有所有依赖项来重现它)。

您的 def plot(x,y,z) 在 def get_data 函数内(在您的 for 循环内)。

您只需要定义一次函数,因此您可以将 def get_data 和 def 绘图线从第 0 列开始。然后您的

if __name__ == '__main__'

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

此外,无需在 for 循环中定义 get_data,您只需使用您正在查找的 DATA 文件调用它。

于 2013-04-17T17:33:59.180 回答
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
于 2013-04-17T18:38:54.243 回答
1

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

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

正如@tstone 所指出的,您的函数定义在循环内,在运行循环之前定义它们,但也要给它们唯一的名称。使用唯一名称,如果您愿意,您仍然可以使用普通plot函数,并且您会发现范围错误(它是在循环中定义的),因为唯一名称(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`

请注意,我更改了 for 的参数get_data,使其没有默认参数,但它将接受一个变量(这里称为DATA来自循环的变量)。

于 2013-04-17T17:32:59.977 回答