質問するログイン新規登録

Q&A

解決済

2回答

348閲覧

価格アンケート回答別に 曲線を描きたい。CHATGPT相談しましたが未解決

Dantesu

総合スコア8

Python

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

0グッド

0クリップ

投稿2023/08/06 08:43

編集2023/08/06 12:12

0

0

実現したいこと

WEBアンケート調査で価格に関する回答別(4種)に滑らかな曲線を描き、検討に使いたい。
Q1,Q2,Q3,Q4には自由回答の金額(数字データ)が得られる予定。現在はダミーデータで練習中

前提

・pythonで計算し可視化したい。
・理想は下記マクロミル社が提唱しているprice2のような事を自分でもやりたい。
https://www.macromill.com/service/data-analysis/price2/
Q1.いくらくらいから「安い」と感じますか。
Q2.いくらくらいから「高い」と感じますか。
Q3.これ以上高いと「高すぎて買えない」と思う価格はいくらくらいですか。
Q4.これ以上安いと「品質に不安を感じる」価格はいくらくらいですか。

試したこと

・(滑らかにできないので)1000円から10000円までのbinを作り該当する件数を全体件数で割り、割合を出す。
・Chat gptに相談したが、グラフが未出力だったり数日間問答してもダミーデータの1-2件ともマッチしない。

該当のソースコード *CHATGPTに相談したものです。下記の通りデータに合わない変なグラフになりました。こちらに合わせなくて問題ございません。

python

1import pandas as pd 2import seaborn as sns 3import matplotlib.pyplot as plt 4 5# CSVファイルを読み込む 6data = pd.read_csv("test_price1.csv") 7 8# 価格帯の設定 9bins = [0, 2000, 4000, 6000, 10000] 10labels = ['0-2000', '2001-4000', '4001-6000', '6001-10000'] 11 12# 価格帯を計算してデータに追加 13data['Price_Range'] = pd.cut(data['Price'], bins=bins, labels=labels) 14 15# 各質問に対する該当割合を計算 16total_responses = len(data) # 全体の回答数 17data['Percentage_Q1'] = data['Q1'].apply(lambda x: 1 if x >= 2000 else 0).groupby(data['Price_Range']).transform('sum') / total_responses 18data['Percentage_Q2'] = data['Q2'].apply(lambda x: 1 if x >= 2000 else 0).groupby(data['Price_Range']).transform('sum') / total_responses 19data['Percentage_Q3'] = data['Q3'].apply(lambda x: 1 if x >= 2000 else 0).groupby(data['Price_Range']).transform('sum') / total_responses 20data['Percentage_Q4'] = data['Q4'].apply(lambda x: 1 if x >= 2000 else 0).groupby(data['Price_Range']).transform('sum') / total_responses 21 22# グラフのプロット 23plt.figure(figsize=(10, 6)) 24sns.set(style='whitegrid') 25sns.lineplot(data=data, x='Price_Range', y='Percentage_Q1', label='Q1', marker='o', color='blue') 26sns.lineplot(data=data, x='Price_Range', y='Percentage_Q2', label='Q2', marker='s', color='green') 27sns.lineplot(data=data, x='Price_Range', y='Percentage_Q3', label='Q3', marker='^', color='orange') 28sns.lineplot(data=data, x='Price_Range', y='Percentage_Q4', label='Q4', marker='D', color='red') 29 30# グラフの装飾 31plt.xlabel('Price Range') 32plt.ylabel('Percentage of Respondents') 33plt.title('Percentage of Respondents by Price Range') 34plt.grid(True) 35plt.gca().yaxis.set_major_formatter('{:.0%}'.format) # 垂直軸を%表記にする 36plt.ylim(0, 1) # 垂直軸の範囲を0%から100%に設定 37 38# グラフを表示 39plt.tight_layout() # レイアウトを調整して重なりを解消 40plt.show()

イメージ説明
ご参考
趣旨踏まえた範囲内で乱数で作成したダミーデータ *上記コードで参照しているtest_price.csvの内容
下記の他にPrice列(こちらの画面で見辛いため削除)があり、binの基準として1000円から1000円ずつ10000円まで値があります。

|Q1 |Q2 |Q3 |Q4 |
3000 7000 10000 1500
1500 2900 8000 300
1169 5347 6496 695
927 2712 9574 400
1042 4402 7456 253
1048 5607 7171 105
1155 5319 6747 231
713 4198 7469 271
522 3920 8276 227
796 5989 5973 181

1079 5741 9683 146
541 3959 5089 291
698 3110 7165 185
814 4475 7334 604
1027 5283 9624 169
1101 5568 6817 266
1148 3649 8574 240
1049 2766 7968 113
1154 4289 5254 545
951 5497 7042 440
579 3911 8631 300
941 4542 9875 264
1112 4552 7130 318
680 4624 9846 276
1147 3134 5597 270
1072 3451 7647 727
1064 4825 8290 407
667 4420 5969 434
1025 4901 8115 579
724 4414 5300 207
1123 5237 9626 464
568 2588 8484 519
646 3584 5872 596
738 5752 5767 395
632 5296 8781 464
751 3747 7264 276
915 3576 5882 537
1096 5946 8203 423
1067 3791 7880 476
558 4294 9644 293
791 3698 7567 173
523 4924 6185 709
767 4643 8629 149
1129 5920 5532 384
1137 5275 9268 454
644 4393 8834 229

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

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

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

meg_

2023/08/06 09:59

コードが見ずらいので「コードの挿入」で記入してください。 現状のグラフと理想のグラフを提示されると回答しやすくなるかと思います。
Dantesu

2023/08/06 10:39

ご指摘ありがとうございます。再編集しました。失礼しました。
退会済みユーザー

退会済みユーザー

2023/08/08 13:10 編集

質問の内容をストレートに表現すると「ある程度細かいピッチのヒストグラムを4本(Q1~Q4)重ねて書きたい」、ということでよろしいですか? > CHATGPTに相談したものです ChatGPTにCSVファイルを放り投げて、「Q1、Q2、Q3、Q4のヒストグラムを4本書きたい」と投げるのもいいかもしれません
Dantesu

2023/08/08 15:22 編集

はい、そうです。 理想は、下記のマクロミルのような曲線を自分でも描いてみたいです。データ数が少ない場合は難しい(実務では箱ひげ図で対応)のかもしれませんが、まずは勉強として https://www.macromill.com/service/data-analysis/price2/
退会済みユーザー

退会済みユーザー

2023/08/08 16:08

データをDFに格納して、np.histogramみたいな関数で適当にbinを分けてmatplotlibでdf.plot()みたいな感じにしたらよさそうですね。まとまった時間ができたときにまだ解決できていないようであれば私もやってみます。 https://deepage.net/features/numpy-histogram.html
Dantesu

2023/08/11 15:16

丁寧にありがとうございます! 私の力量を超えており、コードを理解しようと一つ一つ拝見して調べております。数日経過してしまいましたので、まず御礼のお返事まで失礼します。
退会済みユーザー

退会済みユーザー

2023/08/12 00:49

参考に上げられたURLのグラフを見てもらうと分かるのですが、 •ビンの数が相当多い •なのにビンのそれぞれを足すと100%を超える なので、恐らくですが、線を滑らかにするために内挿(補完)のようなことをしていると思います。同じようにするにはnumpy interpolation みたいなキーワードで検索すると方法自体はたくさん見つかると思います。 が、滑らかにすることに時間を割く価値があればやった方が良いですし、グラフの滑らかさがビジネスの意思決定に関係ないのであれば、「見た目ばっかり良い資料を作ってもしょうがない」と割り切って進めた方が良さそうです。 参考まで
Dantesu

2023/08/12 02:33 編集

重ねてありがとうございました。 今回、chat gptが人間のようなケアレスミスはもちろん、、私さえ書かないようなコードが出てきたり、非常に遠回りになりました。原因の一説は、ユーザの変なインプットだそうなので、AIの学習になればと思い、頂いたコードをchat gptにどう思うか聞いてみました。 提供いただいたコードは、目的を満たすために適切に構築されているように見えます。以下は、コードの主なポイントと評価です: 1. データのロードとヒストグラムの作成に関する処理が適切に行われています。 2. Q1〜Q4の回答ごとにヒストグラムを描画し、カウントを出現確率に変換しています。 3. 各回答のピークや特徴的な点に線や楕円を追加して視覚的な強調を行っています。 4. "Purchasable"(購買可能)の曲線を合計して描画し、購買可能性を示しています。 このコードの評価は、以下のようなポイントで行えるでしょう: - **視覚的な強調と分かりやすさ**: グラフは視覚的に分かりやすく強調されており、回答者の価格感に関する情報を効果的に伝えています。ピークや特徴点の強調、楕円の使用などが良いアイデアです。 - **購買可能性の示唆**: "Purchasable"(購買可能)の曲線が、各価格帯における購買可能性の合計を示しており、購買可能性の傾向を理解しやすくなっています。 - **体裁と読みやすさ**: 軸ラベル、凡例、色、線の種類などが適切に設定され、グラフ全体の体裁が整っています。また、コメントや関数の使用によりコードが読みやすくなっています。 - **改善の余地**: 妥当価格帯の導出部分など、特定の価格帯に関する情報を追加するなど、さらなる改善の余地があります。また、コメントやドキュメンテーションの追加も考慮できます。 総合的に、提供いただいたコードは、目的を達成し、視覚的な強調を活用してデータの特徴を分かりやすく示しています。必要に応じて細かな調整や改善を行いながら、データの解釈や可視化の効果をさらに高めることができるでしょう。
guest

回答2

0

ありがとうございました。本当に助かりました。
熟読し、勉強していきたいと思います

投稿2023/08/12 02:37

Dantesu

総合スコア8

0

ベストアンサー

イメージ説明

Python3

1import pandas as pd 2import numpy as np 3import matplotlib.pyplot as plt 4import matplotlib.patches as patches 5 6# やること:データをロードする 7df = pd.read_csv("./dat.csv") 8 9# やること:ヒストグラムを作る際に、比較しやすいようにレンジをQ1~Q4で共通のビンを作る 10int_bin_count = 15 # ビンの分割数 11common_bin = np.linspace(df.to_numpy().min(),df.to_numpy().max(),int_bin_count +1) 12# print("ヒストグラム作成に使うビン:%s"%(common_bin)) 13 14# やること:カウントの区画数はビンの個数より1つ少なくて使いにくいので、体裁を整えるためにグラフ用の項目軸を先に作る(x軸に使う) 15x_axis = (common_bin + (common_bin[1]-common_bin[0])/2)[:-1] 16 17# Q1~Q4の色を指定し、最後の1つは計算によって「購買可能曲線を」埋める時に使う 18list_color = ["sandybrown","olive","lightseagreen","black","firebrick"] 19list_label = ["Lowest","Reasonable","Highest","Suspicious","Purchasable"] 20 21# グラフに丸を書くための係数 22ellipse_ratio = (x_axis.max() - x_axis.min())/100 23ellipse_height = 10 24 25# 購買可能曲線用の変数を用意する 26y_purchasable = np.zeros(int_bin_count) 27 28# やること:カラムごとにヒストグラムを描画する 29fig,ax = plt.subplots() 30 31# ごちゃごちゃするので円用の関数を用意する 32def draw_circle(x_axis,y_axis,ellipse_height,ellipse_ratio): 33 return patches.Ellipse(xy=(x_axis[y_axis.argmax()], y_axis[y_axis.argmax()]), 34 width=ellipse_height *ellipse_ratio , 35 height=ellipse_height, 36 linewidth=2, 37 ec="blue", 38 linestyle="dotted", 39 fill=False) 40 41for col_name,color,label in zip(df.columns,list_color,list_label): 42 43 # Numpyの関数を使ってヒストグラムのパラメータを得る 44 counts,_ = np.histogram(df[col_name],bins=common_bin) 45 46 # ヒストグラムの度数(カウント)はわかりにくいので、出現確率に変換する(y軸に使う) 47 y_axis = counts/len(df)*100 48 49 # 線を引く 50 ax.plot(x_axis,y_axis,color=color,label=label,linewidth=4) 51 52 53 if label == "Lowest": 54 # 最低価格曲線のピークを処理する 55 ax.axvline(x=x_axis[y_axis.argmax()],color="orangered",linewidth=3) 56 ax.add_patch(draw_circle(x_axis,y_axis,ellipse_height,ellipse_ratio)) 57 ax.text(x_axis[y_axis.argmax()],y_axis[y_axis.argmax()]+ellipse_height*0.8, label + " price",color="blue") 58 59 elif label == "Highest": 60 # 最高価格曲線のピークを処理する 61 ax.axvline(x=x_axis[y_axis.argmax()],color="orangered",linewidth=3) 62 ax.add_patch(draw_circle(x_axis,y_axis,ellipse_height,ellipse_ratio)) 63 ax.text(x_axis[y_axis.argmax()],y_axis[y_axis.argmax()]+ellipse_height*0.8, label + " price",color="blue") 64 65 elif label == "Reasonable": 66 # 妥当価格曲線のピークを処理する 67 ax.axvline(x=x_axis[y_axis.argmax()],color="orangered",linewidth=3,linestyle="dotted") 68 ax.add_patch(draw_circle(x_axis,y_axis,ellipse_height,ellipse_ratio)) 69 ax.text(x_axis[y_axis.argmax()],y_axis[y_axis.argmax()]+ellipse_height*0.8, label + " price",color="blue") 70 71 # 妥当価格帯を適当に導く 72 ax.axvline(x=x_axis[y_axis.argmax()-1],color="orangered",linewidth=1,linestyle="solid") 73 ax.axvline(x=x_axis[y_axis.argmax()+1],color="orangered",linewidth=1,linestyle="solid") 74 75 # あとで描画する購買可能曲線用のデータを用意する 76 if label != "Suspicious": 77 y_purchasable = y_purchasable + y_axis 78 79# 事後に購買可能曲線を処理する 80ax.plot(x_axis,y_purchasable,color=list_color[-1],label=list_label[-1],linewidth=1.5) 81 82 83# グラフの体裁を整える ※Matplotlibで日本語は豆腐になる 84ax.set_xlabel("Price [JPY]") 85ax.set_ylabel("Probability [%]") 86ax.set_xlim((0,df.to_numpy().max())) 87ax.set_ylim((0,100)) 88ax.legend() 89 90# グラフを表示する 91plt.show() 92

投稿2023/08/10 03:07

退会済みユーザー

退会済みユーザー

総合スコア0

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.29%

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

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

質問する

関連した質問