質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

5339閲覧

python 風配図の作成

run1

総合スコア19

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

1クリップ

投稿2018/12/23 12:57

編集2018/12/23 15:26

以下のような風配図を作成しています。風向の割合と風速の割合を同時に表示できる風配図です。イメージ説明

読み込みたいデータの例

295.6,122 270,98 321.3,132 350.7,159 317.3,203 338.4,254 316.1,301 270,342 101.3,239 324,221 60.9,210 331.7,198 358.6,140 12.9,149 252.6,117 300.3,114 286.4,118 78.7,115 86.2,115 0,104

現在作っているプログラムの流れ

以上のようなデータ(1列目が角度、2列目が速度)を読み込み、
①角度を読み込みそれに対応する速度を16方位のリストに分割し、各方位のリストの個数から風向の頻度を求める
②振り分けられた速度をさらに速度ごとに分割する作業を16方位分行い、各速度のリストの個数から風速の頻度を求める
③求めた風速、風向の頻度からグラフを作成する
という流れでプログラムを作成中ですが、①と②の過程に関してただでさえ長くなってしまうリスト化の作業を何回も繰り返すことになってしまい非常に効率が悪いため、②の途中で行き詰まっています。
以下のプログラムでいう
#読み込んだデータを16方位に分ける
#風速を9段階に分ける
の部分で、効率のいい振り分け作業などがあれば教えていただきたいです。
python未経験者で、簡単なコードを利用しゴリ押しでプログラムを作成しているため、非常に効率の悪く見苦しいプログラムになっていますのでご了承ください。
グラフ作成の部分に関してはとりあえずで出力しているだけなので、スルーしてください

該当のソースコード

python

1################################################################################ 2 3import numpy as np 4import matplotlib.pyplot as plt 5 6################################################################################ 7 8#リスト作成(16の方位に分けるため) 9list01 = list() 10list01 = [] 11list02 = list() 12list02 = [] 13list03 = list() 14list03 = [] 15list04 = list() 16list04 = [] 17list05 = list() 18list05 = [] 19list06 = list() 20list06 = [] 21list07 = list() 22list07 = [] 23list08 = list() 24list08 = [] 25list09 = list() 26list09 = [] 27list10 = list() 28list10 = [] 29list11 = list() 30list11 = [] 31list12 = list() 32list12 = [] 33list13 = list() 34list13 = [] 35list14 = list() 36list14 = [] 37list15 = list() 38list15 = [] 39list16 =list() 40list16 = [] 41 42################################################################################ 43 44#データをnumpyで読み込む 45data = np.genfromtxt("test-group0.csv",delimiter=",",encoding='utf_8_sig') 46 47#読み込んだデータを16方位にわける 48for i in range(len(data)): 49 if 0 <= data[i,0] <= 11.25 or 348.75< data[i,0] <= 360: 50 list01.append(data[i,1]) 51 elif 11.25 < data[i,0] <= 33.75: 52 list02.append(data[i,1]) 53 elif 33.75 < data[i,0] <= 56.25: 54 list03.append(data[i,1]) 55 elif 56.25 < data[i,0] <= 78.75: 56 list04.append(data[i,1]) 57 elif 78.75 < data[i,0] <= 101.25: 58 list05.append(data[i,1]) 59 elif 101.25 < data[i,0] <= 123.75: 60 list06.append(data[i,1]) 61 elif 123.75 < data[i,0] <= 146.25: 62 list07.append(data[i,1]) 63 elif 146.25 < data[i,0] <= 168.75: 64 list08.append(data[i,1]) 65 elif 168.75 < data[i,0] <= 191.25: 66 list09.append(data[i,1]) 67 elif 191.25 < data[i,0] <= 213.75: 68 list10.append(data[i,1]) 69 elif 213.75 < data[i,0] <= 236.25: 70 list11.append(data[i,1]) 71 elif 236.25 < data[i,0] <= 258.75: 72 list12.append(data[i,1]) 73 elif 258.75 < data[i,0] <= 281.25: 74 list13.append(data[i,1]) 75 elif 281.25 < data[i,0] <= 303.75: 76 list14.append(data[i,1]) 77 elif 303.75 < data[i,0] <= 326.25: 78 list15.append(data[i,1]) 79 elif 326.25 < data[i,0] <= 348.75: 80 list16.append(data[i,1]) 81 82 83################################################################################ 84 85#風向の頻度の計算(割合) 86r1 = len(list01)/len(data)*100 87r2 = len(list02)/len(data)*100 88r3 = len(list03)/len(data)*100 89r4 = len(list04)/len(data)*100 90r5 = len(list05)/len(data)*100 91r6 = len(list06)/len(data)*100 92r7 = len(list07)/len(data)*100 93r8 = len(list08)/len(data)*100 94r9 = len(list09)/len(data)*100 95r10 = len(list10)/len(data)*100 96r11 = len(list11)/len(data)*100 97r12 = len(list12)/len(data)*100 98r13 = len(list13)/len(data)*100 99r14 = len(list14)/len(data)*100 100r15 = len(list15)/len(data)*100 101r16 = len(list16)/len(data)*100 102 103################################################################################ 104 105#リスト作成(風速を9段階に分けるため) 106l1= list() 107l1 = [] 108l2 = list() 109l2 = [] 110l3 = list() 111l3 = [] 112l4 = list() 113l4 = [] 114l5 = list() 115l5 = [] 116l6 =list() 117l6 = [] 118l7 = list() 119l7 = [] 120l8 = list() 121l8 = [] 122l9 = list() 123l9 = [] 124 125################################################################################ 126 127#風速を9段階に分ける 128for i in range(len(list01)): 129 if 0 <= list01[i] <= 100: 130 l1.append(list01[i]) 131 elif 100 < list01[i] <= 200: 132 l2.append(list01[i]) 133 elif 200 < list01[i] <= 300: 134 l3.append(list01[i]) 135 elif 300 < list01[i] <= 400: 136 l4.append(list01[i]) 137 elif 400 < list01[i] <= 500: 138 l5.append(list01[i]) 139 elif 500 < list01[i] <= 600: 140 l6.append(list01[i]) 141 elif 600 < list01[i] <= 700: 142 l7.append(list01[i]) 143 elif 700 < list01[i] <= 800: 144 l8.append(list01[i]) 145 elif 800 < list01[i] <= 900: 146 l9.append(list01[i]) 147 148################################################################################ 149 150#グラフの作成 151#極座標を16分割 152N = 16 153theta = np.linspace(0.0, 2 * np.pi, N, endpoint=False) 154 155#値の設定 156radiia = r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14,r15,r16 157width = 0.3 #幅 158 159#bottomの設定 160b0=np.array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]) 161 162#積み上げプロット 163ax = plt.subplot(111, projection='polar') 164bar1 = ax.bar(theta, radiia,color="g" ,width=width, bottom=b0) 165 166ax.set_theta_zero_location("N") # 原点は北 167ax.set_theta_direction(-1) # 時計回り 168 169#画像を表示 170#plt.show() 171

イメージ説明

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tiitoi

2018/12/23 13:08

方向は16段階なので、0~22.5, 22.5~25, ... となるとして、風速はどのような範囲で分けるのでしょうか?
run1

2018/12/23 13:10

風速は0-100,100-200となるように分けたいです。
guest

回答2

0

ベストアンサー

①角度を読み込みそれに対応する速度を16方位のリストに分割し、各方位のリストの個数から風向の頻度を求める
②振り分けられた速度をさらに速度ごとに分割する作業を16方位分行い、各速度のリストの個数から風速の頻度を求める

1, 2 でやろうとしていることは、データを風向0 ~ 360で16分割し、さらに風速0~900で9分割する2次元ヒストグラムの作成と考えることができます。

なので、numpy.histogram2d をお使いください。

python

1import matplotlib.pyplot as plt 2import numpy as np 3import seaborn as sns # pip install seaborn 4 5orient, speed = np.loadtxt('test.csv', delimiter=',').T 6 7#orient = np.random.randint(0, 360, 100000) 8#speed = np.random.randint(0, 900, 100000) 9 10x_edges = np.arange(0, 901, 100) 11y_edges = np.linspace(0, 360, 17) 12H = np.histogram2d(np.mod(orient + 11.25, 360), speed, 13 bins=(y_edges, x_edges))[0].astype(int) 14print(H.shape) # (16, 9) 15 16sns.set() 17# 目盛りのラベルを設定する。 18xlabels = ['{} ~ {}'.format(start, end) 19 for start, end in zip(x_edges, x_edges[1:])] 20ylabels = ['N', 'NNW', 'NW', 'WNW', 21 'W', 'WSW', 'SW', 'SSW', 22 'S', 'SSE', 'SE', 'ESE', 23 'E', 'ENE', 'NE', 'NNE'] 24# ヒートマップを作成する。 25sns.heatmap(H, annot=True, cmap='Reds', fmt='d', 26 xticklabels=xlabels, yticklabels=ylabels, cbar=False) 27plt.show()

numpy.histogram2d() の返り値 H の内容は以下の画像を見るとわかるかと思います。各要素は該当する個数を表しています。

イメージ説明

追記

(元の角度 + 11.25) mod 360 としてから、ヒストグラムを作成すればよいです。mod をとるのは 元の角度が 350 の場合、350 + 11.25 = 361.25 となるので、361.25 mod 360 = 1.25 とするためです。

['-11.25 ~ 11.25', '11.25 ~ 33.75', '33.75 ~ 56.25', '56.25 ~ 78.75', '78.75 ~ 101.25', '101.25 ~ 123.75', '123.75 ~ 146.25', '146.25 ~ 168.75', '168.75 ~ 191.25', '191.25 ~ 213.75', '213.75 ~ 236.25', '236.25 ~ 258.75', '258.75 ~ 281.25', '281.25 ~ 303.75', '303.75 ~ 326.25', '326.25 ~ 348.75']

['0.0 ~ 22.5', '22.5 ~ 45.0', '45.0 ~ 67.5', '67.5 ~ 90.0', '90.0 ~ 112.5', '112.5 ~ 135.0', '135.0 ~ 157.5', '157.5 ~ 180.0', '180.0 ~ 202.5', '202.5 ~ 225.0', '225.0 ~ 247.5', '247.5 ~ 270.0', '270.0 ~ 292.5', '292.5 ~ 315.0', '315.0 ~ 337.5', '337.5 ~ 360.0']

投稿2018/12/23 13:30

編集2018/12/23 17:04
tiitoi

総合スコア21954

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

run1

2018/12/23 15:25

histogram2dという機能があるのですね!とても便利な機能ですね。 早速試したのですが、データ数を増やしていくと、おかしなことになってしまいました。出力したヒートマップをアップしましたので、見ていただけないでしょうか?
tiitoi

2018/12/23 15:44 編集

おそらく個数が3桁になり、指数表記になったため、レイアウトが崩れたのだと思います。 sns.heatmap() で fmt='d' で整数表記にし、square=False (デフォルト) としたら崩れなくなりました。 他にもいろいろ設定できるので、見た目を変えたければ以下を参考にしてください。 https://pythondatascience.plavox.info/seaborn/heatmap
run1

2018/12/23 15:47

なるほど。ありがとうございます!
run1

2018/12/23 16:24

こちらの回答を参考にプログラムを組んでいたのですが、方向の分け方が若干違うことに気づきました。単純に0〜22.5のように分けるのではなく、たとえば北北東であれば22.5°なので北と北北東の分岐点は11.25°にしたいのです。そのため、北の範囲が0〜11.25、348.75〜360となり単純に16分割するわけにはいかないのですが、その場合どのように表現したら良いのでしょうか?
tiitoi

2018/12/23 17:02

コードを修正しました。 元の角度にオフセット 11.25 を足してから 0~22.5, ... でヒストグラムを作成すると、-11.25 ~ 11.25, ... でヒストグラムを作成したのと同じことになります。
run1

2018/12/23 17:52

質問にもなんどもお答えいただきありがとうございました。こちらのプログラムを利用することで、最初に作っていたプログラムよりもはるかに楽なプログラムを作成することができました。本当にありがとうございました。
guest

0

風配図(windrows)でググると以下の2つがヒットしました。
Making a wind rose with pandas/matplotlib
windrose · PyPI
動作未検証ですが、1番目がわりとそのまま利用できるように思います。

投稿2018/12/23 13:45

can110

総合スコア38233

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

run1

2018/12/23 15:34

1つめのサイトのプログラムが、まさに私が作りたいプログラムです! パッと読んで見たのですがまだ難しいので調べながらじっくり読んでみたいと思います! どうやらmetarというパッケージを使っているようなので、データの扱い方などが違ってくるのでしょうか…? グラフの出力はそのままなので応用させていただきます!
can110

2018/12/23 15:37

すみません、ググって見つけただけなので詳細は分かりません… が、見た目は目的のものに合致しているので参考にはなるかと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問