3

すべてのデータ ファイルを Python のディレクトリにプロットし、結果のプロットを保存しようとしています。私は効率的な python コードを書こうとしているわけではありません(残念ながら): 今のところデータをプロットすることに興味があります。

私は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

私が見ることができるインデントの問題が少なくとも 1 つあります (ただし、これを再現するためのすべての依存関係はありません)。

あなたの def plot(x,y,z) は def get_data 関数の中にあります (これは for ループの中にあります)。

関数を定義する必要があるのは 1 回だけなので、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`

の引数を変更しget_dataて、デフォルトの引数を持たないようにしましたが、変数を受け入れることに注意してください (ここDATAでは、ループから来る変数を呼び出します)。

于 2013-04-17T17:32:59.977 に答える