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

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

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

for文は、様々なプログラミング言語で使われている制御構造です。for文に定義している条件から外れるまで、for文内の命令文を繰り返し実行します。

Python

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

pandas

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

Q&A

解決済

3回答

1541閲覧

Pandas dfのfor文内部におけるスライスと関数の引数使用でのエラー

iwase13

総合スコア11

for

for文は、様々なプログラミング言語で使われている制御構造です。for文に定義している条件から外れるまで、for文内の命令文を繰り返し実行します。

Python

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

pandas

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

0グッド

0クリップ

投稿2021/05/18 14:59

Pandas dfの欠損の補完を検討しています。
dfは、aからdのgroup、各groupに1から5のx値、
各x値に対して欠損を含むy値から構成されています。

group毎にスライスし、各行に対して、
NaN値が有れば、他のxとy値によって補完値yを計算し、
新たな補完値列に値を代入、flag列に真値として1を代入、
実数が有れば、そのまま実数値を補完列に代入、
flag列に偽値として0を代入します。

2番目以降のgroupに対して、補完値が計算できません。
コード内にdfの内容を出力させましたが、
2番目以降のdfが空になっています。
dfのviewではなくcopyを取るなどの工夫は効果が有りませんでした。

python

1import pandas as pd 2import numpy as np 3 4df_all = pd.DataFrame( 5 data = [['a', 1, np.nan], 6 ['a', 2, 1.0], 7 ['a', 3, 3.0], 8 ['a', 4, np.nan], 9 ['a', 5, 2.0], 10 ['b', 1, 1.0], 11 ['b', 2, np.nan], 12 ['b', 3, 3.0], 13 ['b', 4, 3.0], 14 ['b', 5, np.nan], 15 ['c', 1, np.nan], 16 ['c', 2, 2.0], 17 ['c', 3, np.nan], 18 ['c', 4, 3.0], 19 ['c', 5, 1.0], 20 ['d', 1, 2.0], 21 ['d', 2, np.nan], 22 ['d', 3, 4.0], 23 ['d', 4, np.nan], 24 ['d', 5, 2.0]], 25 columns=['group', 'x', 'y']) 26 27print(df_all) 28 29def split_merge(df): 30 groups = df['group'].unique() 31 print('groups: {}'.format(groups)) 32 df_out = df[:1] 33 for k in range(len(groups)): 34 df = df[5*k:5*(k+1)].copy() 35 print() 36 print('df length: {} of {} in split roop {}'.format(len(df), df['group'].unique(), k)) 37 df_temp = interpolate(df) 38 df_out= pd.concat([df_out, df_temp]) 39 df_out = df_out[1:] 40 df_out['flag'] = df_out['flag'].astype('int8') 41 return df_out 42 43def interpolate(df): 44 df['cal_y'] = np.nan * len(df) 45 df['flag'] = np.nan * len(df) 46 print('---splited df in interpolate function---') 47 print('df length: {}'.format(len(df))) 48 for i in range(len(df)): 49 if pd.isna(df.at[i,'y']): 50 #print('---splited df in interpolate function---') 51 print('Detected na at raw {}'.format(i)) 52 df.at[i,'cal_y'] = calculate(i, df) 53 df.at[i,'flag'] = 1 54 else: 55 df.at[i,'cal_y'] = df.at[i,'y'] 56 df.at[i,'flag'] = 0 57 return df 58 59def calculate(i, df): 60 sum_wj = 0 61 sum_wjyj = 0 62 for j in range(len(df)): 63 xi = df.at[i,'x'] 64 xj, yj = df.at[j,'x'], df.at[j,'y'] 65 if (j!=i) & (pd.notna(yj)): 66 wj = 1 / (np.sqrt((xj - xi)**2)) 67 wjyj = wj * yj 68 else: 69 wj = 0 70 wjyj = 0 71 sum_wj += wj 72 sum_wjyj += wjyj 73 yi = sum_wjyj / sum_wj 74 return yi 75 76start = 0 77group_count = 2 78df = df_all[5*start:5*(start + group_count)].copy() 79print(df) 80 81 82df_out = split_merge(df) 83df_out

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

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

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

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

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

meg_

2021/05/18 15:41

言葉だけでは分かりにくいので、欲しい結果のデータフレームを提示出来ますでしょうか?
iwase13

2021/05/18 15:53

早速のご対応ありがとうございます。 最初のgroup 'a'だけ上手く実行できたのですが、NaNがcal_yにて保管されています。 bからdのgroupは出力されません。 group x y cal_y flag 0 a 1 NaN 1.714286 1 1 a 2 1.0 1.000000 0 2 a 3 3.0 3.000000 0 3 a 4 NaN 2.200000 1 4 a 5 2.0 2.000000 0
meg_

2021/05/18 15:56

こちらが「最終的に欲しい結果」ですか?
iwase13

2021/05/18 16:07

エラーが生じており結果の全部を得ているわけではないので、 これは「最終的に欲しい結果」ではありません。 エラーが解消されば、group b以降でも、上記のa groupと同様な結果を得たいです。
ppaul

2021/05/19 00:38

本題ではありませんが、補間の値と正しい値との差が大きすぎるように思います。二次のラグランジュ補間だと、ほとんど誤差は出ないですよ。
iwase13

2021/05/19 07:46

ppaulさん、コメントありがとうございます。 この補完計算はダミーで、実際にはspline補完などリーズナブルなものを適応しようと思っています。
guest

回答3

0

ご質問の回答になっているかどうか良くわかりませんが、こういう方法もあります。
numpyのpolyfitという多項式近似とpoly1dによる近似式による値を使ったものです。
別の近似式を使うのであれば、f=の部分をその関数定義に変更すれば使えるはずです。
df_listは長さ4のリストでa,b,c,dそれぞれが入っています。
全部合わせて長さ20のDataFrameの方がdf_concatです。

python

1import pandas as pd 2import numpy as np 3 4def modify(df): 5 f = np.poly1d(np.polyfit(df.dropna()['x'], df.dropna()['y'], 2)) 6 dfcopy = df.copy() 7 dfcopy['y'] = df.apply(lambda row: f(row['x']) if row['flag'] else row['y'], axis=1) 8 return dfcopy 9 10df_all['flag'] = 1 11df_all['flag'].where(df_all['y'].isna(), 0, inplace=True) 12df_list = [modify(df) for _, df in df_all.groupby('group')] 13print(df_list[3]) 14df_concat = pd.concat(df_list) 15print(df_concat)

実行結果

python

1>>> print(df_list[3]) 2 group x y flag 315 d 1 2.0 0 416 d 2 3.5 1 517 d 3 4.0 0 618 d 4 3.5 1 719 d 5 2.0 0

python

1>>> print(df_concat) 2 group x y flag 30 a 1 -2.666667 1 41 a 2 1.000000 0 52 a 3 3.000000 0 63 a 4 3.333333 1 74 a 5 2.000000 0 85 b 1 1.000000 0 96 b 2 2.333333 1 107 b 3 3.000000 0 118 b 4 3.000000 0 129 b 5 2.333333 1 1310 c 1 -1.000000 1 1411 c 2 2.000000 0 1512 c 3 3.333333 1 1613 c 4 3.000000 0 1714 c 5 1.000000 0 1815 d 1 2.000000 0 1916 d 2 3.500000 1 2017 d 3 4.000000 0 2118 d 4 3.500000 1 2219 d 5 2.000000 0

投稿2021/05/20 09:43

ppaul

総合スコア24670

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

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

iwase13

2021/05/25 14:20

ppaulさん 返信遅れ申し訳ありません。 難しかったので、咀嚼するのに時間を要しました。 dfのスライス、falg付けにForを使っていませんね。 近似はy値がNaNの行をdropして2次関数fを定義、lambda関数でyの近似値を代入するのですね。 自分でもこんなコードが書けるように精進したいと思います。 質問が1つ。 if row['flag'] はrow['flag']が「1」ならTrueと扱われるのでしょうか?
guest

0

ベストアンサー

split_merge()のなかのループで、dfを変更してしまっているのが問題です。

python

1 for k in range(len(groups)): 2 df = df[5*k:5*(k+1)].copy()

ループの1回目で、df = df[0:5]と5行目までだけのものになってしまうので、次のループで6行目以降を取り出したときに空になります。
違う変数名を使うようにすればいいです。

上記変更をすると、interpolate()calculate()で別のエラーが出ると思います。

python

1 for i in range(len(df)): 2 if pd.isna(df.at[i,'y']):

df.at[i, 'y']iは行番号ではなくインデックスで指定します。
なのでrangeを使った行番号ではなく、インデックスでループしないといけないです。

python

1 for i in df.index: 2 if pd.isna(df.at[i,'y']):

投稿2021/05/19 00:57

bsdfan

総合スコア4794

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

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

iwase13

2021/05/19 07:57

bsdfanさん、ありがとうございます! 正常に動くようになりました。 動作しない理由、対策も分かりやすく説明して下さり勉強になりました。 in df.indexで何がリストになっているかを確認してみました。 スライスして別名で作られたdf_xxに対しても、 元のdfのindexを番号が割り当てられているのですね。 そうであれば、range(len(df))では、.locなどが出来ないのも納得です。
guest

0

当方ではエラーが発生しなかったため、split_merge()を変更しgroupby()を使用しました。

Python

1def split_merge(df): 2 df = df.reset_index(drop=True) 3 df_out = interpolate(df) 4 df_out['flag'] = df_out['flag'].astype('int8') 5 return df_out

python

1result = df_all.groupby('group').apply(split_merge) 2print(result) 3# group x y cal_y flag 4#group 5#a 0 a 1 NaN 1.714286 1 6# 1 a 2 1.0 1.000000 0 7# 2 a 3 3.0 3.000000 0 8# 3 a 4 NaN 2.200000 1 9# 4 a 5 2.0 2.000000 0 10#b 0 b 1 1.0 1.000000 0 11# 1 b 2 NaN 2.200000 1 12# 2 b 3 3.0 3.000000 0 13# 3 b 4 3.0 3.000000 0 14# 4 b 5 NaN 2.714286 1 15#c 0 c 1 NaN 2.052632 1 16# 1 c 2 2.0 2.000000 0 17# 2 c 3 NaN 2.200000 1 18# 3 c 4 3.0 3.000000 0 19# 4 c 5 1.0 1.000000 0 20#d 0 d 1 2.0 2.000000 0 21# 1 d 2 NaN 2.857143 1 22# 2 d 3 4.0 4.000000 0 23# 3 d 4 NaN 2.857143 1 24# 4 d 5 2.0 2.000000 0

投稿2021/05/18 16:58

meg_

総合スコア10760

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

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

iwase13

2021/05/19 07:44

有難うございました。 残念ながら、df = df.reset_index(drop=True) を使ったsplit_merge() では、NaNがNaNのまま出力され、megさんのような結果は得られませんでした。 また、この方法では、補完の計算をgroup毎で演算するのではなく、全groupの全行に対して演算してしまうと思料します。
meg_

2021/05/19 10:54

「df_all.groupby('group').apply(split_merge)」でグループ毎にsplit_mergeを適用しているはずですが、質問者さんの環境では動作しませんでしたか?
meg_

2021/05/19 10:57

bsdfanさんの回答にて解決されたようなので良かったです。もしかして、あえてgroupbyを使用しない方法での実装を希望されてましたか?
iwase13

2021/05/19 13:10

megさん、ありがとうございます。 動作いたしました。理解が足りませんでした。 groupbyについては知見がなく、避けていた訳ではありません。 df.allに対して直接.groupby('group').apply(split_merge)メソッドを適応させ、resultとして結果を得るのですね。私が作ったコードのsplit_merge()だけをmegさんのsplit_merge()に置き換えただけだったので正常に動作しませんでした。 df_all.groupby('group')でデータ分割し、.apply(split_merge)で分割データに対して演算するのですね。for文を使わないので、大量データの場合は、megさんの方法が高速かもしれませんね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問