Python / 3Dプロットのために2次元データを結合(実験データの3Dプロット用)

(11/23)色々修正しました。

複数の2次元データを結合し、3Dプロット(いずれはカラープロット)します。
Python3で書いてます。



やりたかったこと

通常実験では「xを変化させたときのzの応答」を調べますが、そこで更にyというパラメータを変化させて「x、yを変化させたときのzの応答」を得ることもできます。ただ、測定ではあくまでも一方のパラメータを固定しないといけないので、結局用意できるのは『あるyに対して「xを変化させたときのzの応答」を測定したデータ』の集合になります。例として色々な温度で試料のI-V特性を調べるような状況を考えば、実験で得られるデータは下のような感じになると思います。


20161120_samplename_I-V_0K.dat   ※0KでのI-V
20161120_samplename_I-V_100K.dat  ※100KでのI-V
20161120_samplename_I-V_200K.dat ※200KでのI-V
20161120_samplename_I-V_300K.dat ※300KでのI-V
20161120_samplename_I-V_400K.dat ※400KでのI-V
20161120_samplename_I-V_500K.dat ※500KでのI-V

一つ一つの中身は、例えば「20161120_samplename_I-V_0K.dat」だと

電圧   電流
-1      -0.789
-0.995  -0.765
-0.990  -0.754
-0.985  -0.739


こんな感じでしょうか。

これらのデータから3Dプロットやカラープロットを作成するためには、上記のファイルをすべて結合し、ファイル名から読み取った温度を新たに列として書き込んだ3次元のデータが必要です。つまり最終的に欲しいデータは下のような感じです。(初めからデータに温度を書き込んでいれば結合だけで済む話ですが…。)


温度  電圧   電流
0      -1      -0.789
0      -0.995  -0.765
0      -0.990  -0.754
0      -0.985  -0.739

100    -1      -0.789
100    -0.995  -0.765
100    -0.990  -0.754
100    -0.985  -0.739

200    -1      -0.789
200    -0.995  -0.765

(スペースを入れて整えてますが実際はタブ区切りです。電流の右に第3、第4の列が続いても構いません。)


ということで、このようにファイル名から(例として)温度を読み取り、それを新しい列として追加しつつ、フォルダ内の全てのファイル(データ)を結合するプログラムをPythonで書きました。


できたコード
import re, glob
from functools import cmp_to_key

#ファイルのソート--------------------------------------------------------------
filelist = glob.glob('*K*.dat')
filelist2 = []

for x in filelist:
    match = re.match('(.*)_(.*)K(.*)', x)
    tuple = (match.group(2), x)
    filelist2.append(tuple)

def cmp(a, b):
    if a == b: return 0
    return -1 if a < b else 1

def cmptuple(a, b):
    return cmp(float(a[0]), float(b[0]))

filelist = [x[1] for x in sorted(filelist2, key=cmp_to_key(cmptuple))]

#ファイルの結合--------------------------------------------------------------
with open('combined_file.dat', 'w') as combine:
    for filename in filelist:
        match = re.match('(.*)_(.*)K(.*)', filename)
        K = match.group(2)
        with open(filename, 'r') as read:
            for line in read.readlines()[0:]:
                line2 = K + '\t' + line
                combine.writelines(line2)


どうもsyntaxhighlighterで貼り付けると半角スペースがおかしくなるみたいです。このままだとエラーを吐くので、ここからコピーするときはプログラム上のインデントを一旦tab(または半角スペース×4)で置き換えてから使ってください。(インデントの深さは変えないように)よくわからないけどうまくいってるみたい…。

これを例えばcombine.pyとかいう名前で、datファイルを置いているディレクトリに保存して、ターミナルとかコマンドプロンプトで
$ python combine.py
と実行すれば、上で必要としていたcombined_file.datが出力されます。


説明(細かい使い方)

ファイルのソート
  1. filelist = glob.glob('*K*.dat')
    filelistはglob関数で取得しています。その際必要なファイルだけ取得するように、引数は'*K*.dat'としています。*はワイルドカードで、任意の文字列がひっかかります。この場合ファイル名(頭、お尻は除く)にKを含み、拡張子がdatのファイルだけリスト化されます。適宜変更してください。
  2. match = re.match('(.*)_(.*)K(.*)', x)
    tuple = (match.group(2), x)

    正規表現でパターンを検索し、温度でソートするため、温度をグループとして取り出してタプルに入れています。(.*)は任意の文字列なので、検索では20161120_sample1_I-V_0K.dat(20161120_sample1_I-V)_(0)K(.dat)という感じで引っかかるようになっています。でいま必要な温度は2番目のグループなので、match.group(2)で引っこ抜いてます。適宜変更してください。
ファイルの結合
  1. re.match()match.group()のところは上と同じです。ファイル名から抜き出す箇所に応じて適宜変更してください。
  2. for line in read.readlines()[0:]:
    リスト化したファイルから一行ずつデータを読み込みます。readlines()[0:]:のとこですが、[0:]0行目から読み込むようにしています。元のデータにヘッダーなど、スキップしないといけない行があれば[1:]みたいな感じで適宜変更してください。

ソートしたファイルを結合するだけで、新しく列を作る必要なんてねえって場合はファイルの結合の部分を

with open('combined_file.dat', 'w') as combine:
    for filename in filelist:
        with open(filename, 'r') as read:
            for line in read.readlines()[0:]:
                combine.writelines(line)

に変更してください。


3Dプロット

で、暫定ですが上でできたcombined_file.datの3Dプロットは下のを同じディレクトリで実行すればできます。

from pylab import *
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
import numpy as np

f = open('combined_file.dat', 'r')
lines = f.readlines()
f.close()

x1 = []
y1 = []
z1 = []

for line in lines:
    p = line.split()
    x1.append(float(p[0])) #1列目がx
    y1.append(float(p[1])) #2列目がy
    z1.append(float(p[2])) #3列目がz

ax = axes3d.Axes3D(figure())

ax.plot3D(x1, y1, z1, color=(0.0, 0.0, 1,0))
ax.scatter3D(x1, y1, z1, color=(1.0, 0.0, 0.0), marker="o", s=10)

show()


次回は3Dプロットとカラープロットの話を書く予定です。


Python / 3Dプロットのために2次元データを結合(実験データの3Dプロット用) Python / 3Dプロットのために2次元データを結合(実験データの3Dプロット用) Reviewed by mug on 11/20/2016 Rating: 5

0 件のコメント:

Powered by Blogger.