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

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

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

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

pandas

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

Q&A

解決済

1回答

372閲覧

データフレームを結合し、名前の変更と加重平均を算出する

YYjiji

総合スコア2

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

pandas

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

0グッド

1クリップ

投稿2022/06/01 07:29

前提

材料開発においてMIを使用したいと考えております。
材料a,b,cを比率a : b : c=A:B:Cで混合する実験を想定しています。a,b,cには種類があり、例えばaはa_1とa_2があります。
a,b,cにはそれぞれx,y,zという特性値をもっており、別のデータフレームにまとまっています。

行いたいことは、材料の混合比率表に特性値を結合し、どの材料の特性値かが分かるようにしたいです。
更に特性値ごとに材料の添加量で加重平均を計算したカラムを新たに追加したいです。

一つずつ書くことはできるのですが、実データでは膨大な特性値がありプログラム化したいです。
for文などがよくわかっておらず、困っております。大変恐縮ですが、どなたかお詳しい方ご教授いただけないでしょうか。

実現したいこと

以下のコードをプログラム化する

発生している問題・エラーメッセージ

エラーメッセージ

該当のソースコード

python

1import pandas as pd 2 3# 材料a,b,cを比率a:b:c=A:B:Cで混合する 4# a,b,cには種類があり、例えばaはa_1とa_2があります。 5df = pd.DataFrame({'a': ['a_1', 'a_1', 'a_2'], 'b': ['b_1', 'b_2', 'b_3'], 'c':['c_1', 'c_1', 'c_2'] 6 ,'A':[0.5,0.2,0.3],'B':[0.2,0.3,0.4],'C':[0.3,0.5,0.3]}) 7 8# a,b,cはそれぞれx,y,zという特性値をもっており、別のデータフレームにまとまっています。 9df_a = pd.DataFrame({'a':['a_1','a_2'],'x': [1, 2], 'y': [4, 5],'z':[7, 8]}) 10df_b = pd.DataFrame({'b':['b_1','b_2','b_3'],'x': [3, 4, 5], 'y': [6, 7, 8],'z':[9, 10, 11]}) 11df_c = pd.DataFrame({'c':['c_1','c_2'],'x': [5, 6], 'y': [8, 9],'z':[11, 12]}) 12 13# 材料の混合表(df)に特性値(df_a,df_b,df_c)を結合し、どの材料の特性値かが分かるようにする 14df_new = df.merge(df_a,on='a') 15df_new = df_new.rename(columns={'x':'x_a','y':'y_a','z':'z_a'}) 16df_new = df_new.merge(df_b,on='b') 17df_new = df_new.rename(columns={'x':'x_b','y':'y_b','z':'z_b'}) 18df_new = df_new.merge(df_c,on='c') 19df_new = df_new.rename(columns={'x':'x_c','y':'y_c','z':'z_c'}) 20 21# 特性値ごとに材料の添加量で加重平均を計算したカラムを新たに追加 22df_new['x_ave'] = (df_new['x_a']*df_new['A']+df_new['x_b']*df_new['B']+df_new['x_c']*df_new['C'])/(df_new['A']+df_new['B']+df_new['C']) 23df_new['y_ave'] = (df_new['y_a']*df_new['A']+df_new['y_b']*df_new['B']+df_new['y_c']*df_new['C'])/(df_new['A']+df_new['B']+df_new['C']) 24df_new['z_ave'] = (df_new['z_a']*df_new['A']+df_new['z_b']*df_new['B']+df_new['z_c']*df_new['C'])/(df_new['A']+df_new['B']+df_new['C']) 25

試したこと

ここに問題に対して試したことを記載してください。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

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

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

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

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

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

guest

回答1

0

ベストアンサー

そもそもなのですが、私なら元データを以下のように管理します。

  • 材料は'a_1' -> type='a' + id='1' のように種別(type)と種別内での識別番号(id)の組として管理する
  • 混合表と特性表は正規化する(列毎ではなく行毎にデータを持たせる)

上記によって、以下のコード例のように一般的なpandas演算操作のみで目的の値を得ることができます。
また、材料や特性が増えても、処理コードはほぼ変更する必要なく動作する、というメリットもあります。

なお、結果の見やすさのために行毎のデータを列毎に展開したい場合は基本的にはpivot_tableが使えます。

Python

1import pandas as pd 2from io import StringIO 3 4# 混合表 5s = """mix_id,mat_type,mat_id,mix_ratio 61,a,1,0.5 71,b,1,0.2 81,c,1,0.3 92,a,1,0.2 102,b,2,0.3 112,c,1,0.5 123,a,2,0.3 133,b,3,0.4 143,c,2,0.3""" 15df_mix = pd.read_csv(StringIO(s)) 16 17# 特性表 18s = """mat_type,mat_id,char_type,char_val 19a,1,x,1 20a,1,y,4 21a,1,z,7 22a,2,x,2 23a,2,y,5 24a,2,z,8 25b,1,x,3 26b,1,y,6 27b,1,z,9 28b,2,x,4 29b,2,y,7 30b,2,z,10 31b,3,x,5 32b,3,y,8 33b,3,z,11 34c,1,x,5 35c,1,y,8 36c,1,z,11 37c,2,x,6 38c,2,y,9 39c,2,z,12""" 40df_char = pd.read_csv(StringIO(s)) 41 42# 混合表と特性表を結合し特性毎に混合比率に応じた値を算出 43df_merge = pd.merge(df_mix, df_char, on=['mat_type', 'mat_id'], how='outer') 44df_merge = df_merge.sort_values(['mix_id', 'mat_type', 'mat_id', 'char_type']) 45df_merge['val'] = df_merge['char_val'] * df_merge['mix_ratio'] 46#print(df_merge) 47 48# 特性毎の値を集計演算 49df_val = df_merge.groupby(['mix_id', 'char_type']).sum('val').reset_index() # 提示例に合わせて平均ではなく合計を算出 50df_val = df_val[['mix_id','char_type','val']] 51#print(df_val) 52 53# 混合表にて材料を列に展開 54df_pmix = pd.pivot_table(df_mix, index='mix_id', columns=['mat_type']) 55#print(df_pmix) 56 57# 集計表にて物性を列に展開 58df_pval = pd.pivot_table(df_val, index='mix_id', columns=['char_type']) 59#print(df_pval) 60 61# それぞれ列展開した混合表と集計表を結合 62df = pd.merge(df_pmix, df_pval, on='mix_id') 63print(df) 64""" 65 mat_id mix_ratio val 66mat_type a b c a b c x y z 67mix_id 681 1 1 1 0.5 0.2 0.3 2.6 5.6 8.6 692 1 2 1 0.2 0.3 0.5 3.9 6.9 9.9 703 2 3 2 0.3 0.4 0.3 4.4 7.4 10.4 71"""

投稿2022/06/02 06:04

can110

総合スコア38262

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

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

YYjiji

2022/06/03 08:11

can110様ご回答ありがとうございます。私には高度すぎて内容が理解できていないのですが、勉強させていただきます。データ管理についてもアドバイスいただきましてありがとうございます。ベストアンサーとさせていただきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問