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

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

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

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

pandas

Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

Q&A

解決済

2回答

1529閲覧

[Pandas] 複数要素の度数分布表とヒストグラム

luciano

総合スコア11

Python

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

pandas

Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

0グッド

0クリップ

投稿2021/02/15 07:47

Pandas初心者です。

天気と湿度の関係を度数分布とヒストグラムで表そうとしています。
具体的には、下記の図の左側のデータから右側のような度数分布表を目指しています。

イメージ説明

自分でも調べてみて、例えば「晴れ」の列のみの場合は、「晴れ」だけを抽出した別途dfを作成してmatplotlib.pyplot.histを使ってヒストグラムを書くことは出来ました。

しかし、実際に欲しいのは、「湿度が10%以上20%未満」の時に、「晴れ/曇り/雨」がそれぞれ何回出現するかというデータです。出来ましたら、それを使ってのヒストグラムの書き方もお教え頂ければ助かります。

どうか、よろしくお願いします。

[環境]
Mac Os Catalina
Python 3.8
Jupyter Notebook 6.0.1
pandas 0.25.1

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

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

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

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

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

jeanbiego

2021/02/15 07:55 編集

出来たコードと、テスト用のデータ(ファイルのURLか、コピペできる形式のもの)とを記載したほうが回答がつきやすいかと思います。
ppaul

2021/02/15 07:59

湿度が10%の場合は、0~10%と10~20%のどちらに入れるのですか。そして、0%と100%はどこに入れるのですか?
guest

回答2

0

ベストアンサー

度数分布票の作成です。
まず元データの作成。

python

1import pandas as pd 2import io 3 4indata = '''天気 湿度 5晴れ 20% 6曇り 60% 7晴れ 0% 8曇り 10% 9曇り 60% 10曇り 25% 11雨 100% 12晴れ 15% 13曇り 70% 14雨 60%''' 15 16with io.StringIO(indata) as f: 17 df = pd.read_csv(f, sep=' +', engine='python') 18 19print(df)

実行結果

python

1... 2>>> print(df) 3 天気 湿度 40 晴れ 20% 51 曇り 60% 62 晴れ 0% 73 曇り 10% 84 曇り 60% 95 曇り 25% 106100% 117 晴れ 15% 128 曇り 70% 13960%

度数分布表の作成です。

python

1import pandas as pd 2import numpy as np 3 4def classify(row): 5 m = float(row['湿度'][:-1]) 6 level = int(m/10)*10 7 if level == 100: 8 level = 90 9 return f'{level}%-{level+10}%' 10 11df['範囲'] = df.apply(classify, axis=1) 12df2 = pd.concat([df, pd.get_dummies(df['天気'])], axis=1).drop(['天気','湿度'], axis=1) 13df3 = pd.pivot_table(df2, index='範囲', values=['晴れ', '曇り', '雨'], aggfunc=np.sum) 14 15df_i = pd.DataFrame({'範囲':[f'{i}%-{i+10}%' for i in range(0,100,10)]}) 16df4 = pd.merge(df_i, df3, on='範囲', how='outer').fillna(0).astype({'晴れ':int, '曇り':int, '雨':int}) 17print(df4)

実行結果

python

1>>> print(df4) 2 範囲 晴れ 曇り 雨 30 0%-10% 1 0 0 41 10%-20% 1 1 0 52 20%-30% 1 1 0 63 30%-40% 0 0 0 74 40%-50% 0 0 0 85 50%-60% 0 0 0 96 60%-70% 0 2 1 107 70%-80% 0 1 0 118 80%-90% 0 0 0 129 90%-100% 0 0 1

グラフの表示です。

python

1import matplotlib.pyplot as plt 2x_datas = [1, 2, 3, 4, 5,6 ,7, 8, 9, 10] 3fine = df4['晴れ'] 4cloudy= df4['曇り'] 5rain = df4['雨'] 6fig = plt.figure() 7ax = fig.add_subplot(1, 1, 1) 8ax.bar(x_datas, fine, label='晴れ') 9ax.bar(x_datas, cloudy, bottom=fine, label='曇り') 10ax.bar(x_datas, rain, bottom=cloudy, label='雨') 11plt.xticks(x_datas, df4['範囲']) 12plt.legend() 13plt.show()

実行結果
ヒストグラム

投稿2021/02/15 13:34

ppaul

総合スコア24670

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

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

luciano

2021/02/16 01:38

ご回答ありがとうございます。 また、返答が遅くなり申し訳ありません。 お示しいただいた結果は、望んだ通りのものです。 ただ、次の点でつまずいてしまいました。 ”def classify(row):”が、範囲(階級)を作るためのものかと思います。 元のdfにおいて「湿度」のデータ形式は「float64」(小数そのまま)となっているためか、頂いたコードをそのまま試してみると、TypeError: ("'float' object is not subscriptable", 'occurred at index 0')が出てしまいます。 この点、どう書き換えれば良いか、お手数ですがご教示頂ければ幸いです。 なお、範囲の端点は、「以上〜未満」としていますが、ご指摘の通り、これでは100%(=1.0)が入らなくなるので、Excelでは最後の階級だけ「0.9以上」のように処理していました。
phoepsilonix

2021/02/16 02:09

以下の行だけ修正してみてください。 m = float(row['湿度'])
ppaul

2021/02/16 13:07

pandasでcsvを読み込むと、20%というのは文字列になっているので、[:-1]で最後の文字を取り除き、'20'を数にするためにfloat()を使っています。 xlsxから読み込む場合は、20%は0.2という浮動小数なので、この処理は必要ありません。 phoepsilonixさんの書かれている m = float(row['湿度']) でもいいですが、 m = row['湿度'] でも十分です。
ppaul

2021/02/16 13:56

小数をパーセントにしたいのだから100倍する必要がありました。 m = row['湿度']*100 としてください。
luciano

2021/02/17 01:49

ppaul様 ご指摘の通りでうまく動くようになりました。 有難うございました。
luciano

2021/02/17 01:50

phoepsilonix様 有難うございました。
guest

0

dfは下記とする。

天気 湿度 0 晴れ 20 1 晴れ 50 2 雨 90 3 曇り 70 4 晴れ 10 5 雨 60 6 雨 65 7 曇り 45 8 晴れ 30

python

1df1 = df[df['天気']=='晴れ'] 2y1, x1 = np.histogram(df1['湿度'], bins = 10, range=(0, 100)) 3df2 = df[df['天気']=='曇り'] 4y2, x2 = np.histogram(df2['湿度'], bins = 10, range=(0, 100)) 5df3 = df[df['天気']=='雨'] 6y3, x3 = np.histogram(df3['湿度'], bins = 10, range=(0, 100)) 7plt.bar(x1[1:] - 3, y1, width=3, label='晴れ') 8plt.bar(x2[1:], y2, width=3, label='曇り') 9plt.bar(x3[1:] + 3, y3, width=3, label='雨') 10plt.legend() 11plt.show()

イメージ説明

投稿2021/02/15 11:48

編集2021/02/16 04:23
meg_

総合スコア10760

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

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

luciano

2021/02/16 01:38

ご回答ありがとうございます。 また、返答が遅くなり申し訳ありません。 頂いたコードを試してみました。 実際のデータでやってみると、同じ階級内に「晴れ/曇り/雨」のそれぞれが同時に存在するので、ヒストグラムの棒が被ってしまいます。これを同階級内でそれぞれの棒が横に並ぶか、もしくは縦に積み上げるような感じには出来るでしょうか?
meg_

2021/02/16 04:24

上書きプロットしていた箇所を修正しました。数値はバーの幅に合わせて調整してください。
luciano

2021/02/17 01:50

meg_様 有難うございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問