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

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

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

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

Python

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

pandas

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

Q&A

解決済

4回答

1299閲覧

条件に合致するデータフレームの行番号,列番号(列名)を高速で抽出処理する方法を教えて欲しい

mini1988

総合スコア56

Python 3.x

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

Python

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

pandas

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

0グッド

1クリップ

投稿2021/07/29 05:05

編集2021/07/29 05:43

困っていること

元のデータフレームと新規のデータフレームを比較して、条件に合致する行番号,列番号(列名)を抽出したいと考えています。

ただし、現在私が作成したスクリプトは非常に動作が遅いため、高速化したいのですが、どなたかfor文を極力使わずに高速化できるアドバイスをいただけないでしょうか?

どなたか分かる方、ご教示お願いします。

やりたいこと

新規データフレーム(df_new)の全て行を元データフレーム(df_old)の各列上限下限と比較し、各列のいずれかが上限下限を超えた場合に、行番号(インデックス)と列番号(列名)を表示させるようにしたい、というものです。

x_old=np.array([[0.05,0.03,0.60], [0.94,0.84,0.06], [0.78,0.31,0.60], [0.46,0.90,0.82]]) x_new=np.array([[0.715194,0.911633,0.919818], [0.007843,0.280836,0.116867], [0.785161,0.788028,0.876988], [0.082946,0.490916,0.333131]]) df_old=pd.DataFrame(x_old,columns=["A","B","C"]) df_new=pd.DataFrame(x_new,columns=["A","B","C"]) for i in range(len(df_new)): error=[] for c in df_new.columns: if df_old.describe().loc[["min"],c].values[0]<=df_new.loc[i,c] \ and df_new.loc[i,c]<=df_old.describe().loc[["max"],c].values[0]: pass else: error.append(c) if len(error)>0: print(i,error) ------------------------------ 以下、print文で表示される内容 0 ['B', 'C'] 1 ['A'] 2 ['C']

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

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

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

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

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

guest

回答4

0

ベストアンサー

python

1for i, c in enumerate((x_old.max(0) < x_new) | (x_old.min(0) > x_new)): 2 print(f'{i}行目:', df_new.columns[c].tolist()) 3 4# 0行目: ['B', 'C'] 5# 1行目: ['A'] 6# 2行目: ['C'] 7# 3行目: []

投稿2021/07/30 06:52

kirara0048

総合スコア1399

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

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

mini1988

2021/08/01 04:25

ありがとうございます!!!ご提案させてもらった中で、計測時間が一番高速でした。大変助かりました。
guest

0

最小値と最大値が欲しいだけなのに、describe()を使うのは計算の無駄です。
しかも、行ごとに計算しなおしているので余計に時間がかかっています(minとmaxで2回もしています)。
最大値と最小値の計算をループの外で1回だけするようにすれば、それだけでかなり改善します。

python

1old_min = df_old.min() 2old_max = df_old.max() 3for i in range(len(df_new)): 4 error=[] 5 for c in df_new.columns: 6 if old_min[c]<=df_new.loc[i,c] \ 7 and df_new.loc[i,c]<=old_max[c]: 8 pass 9 else: 10 error.append(c) 11 if len(error)>0: 12 print(i,error)

次のように、判定部分をデータフレームのまま計算するとさらに速いと思います。

python

1df_err = (df_new < df_old.min()) | (df_old.max() < df_new) 2for i, *row in df_err.itertuples(): 3 error = list(df_err.columns[row]) 4 if error: 5 print(i, error)

投稿2021/07/29 06:39

bsdfan

総合スコア4794

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

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

mini1988

2021/07/29 08:01

1/15 の時間短縮ができました。ありがとうございました!
guest

0

こういう感じです。

python

1>>> print(df_old) 2 A B C 30 0.05 0.03 0.60 41 0.94 0.84 0.06 52 0.78 0.31 0.60 63 0.46 0.90 0.82 7>>> print(df_new) 8 A B C 90 0.715194 0.911633 0.919818 101 0.007843 0.280836 0.116867 112 0.785161 0.788028 0.876988 123 0.082946 0.490916 0.333131 13>>> df_min = pd.concat([pd.DataFrame(df_old.min(axis=0)).T]*len(df_new), axis=0).reset_index(drop=True) 14>>> 15>>> df_max = pd.concat([pd.DataFrame( df_old.max(axis=0)).T]*len(df_new), axis=0).reset_index(drop=True) 16>>> 17>>> df_result = (df_new < df_min) | (df_new > df_max) 18>>> 19>>> sr_result = df_result.apply(lambda row: [c for c in df_new.columns if row[c]], axis=1) 20>>> 21>>> for i, r in enumerate(sr_result): 22... if r: 23... print(i, r) 24... 250 ['B', 'C'] 261 ['A'] 272 ['C']

投稿2021/07/29 06:37

ppaul

総合スコア24670

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

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

mini1988

2021/07/29 08:02

ありがとうございました!
guest

0

速くしたいということなら、pandasよりnumpyの方が速いらしいですが。下記いかがでしょう。

python3

1import numpy as np 2x_old=np.array([[0.05,0.03,0.60], 3 [0.94,0.84,0.06], 4 [0.78,0.31,0.60], 5 [0.46,0.90,0.82]]) 6 7x_new=np.array([[0.715194,0.911633,0.919818], 8 [0.007843,0.280836,0.116867], 9 [0.785161,0.788028,0.876988], 10 [0.082946,0.490916,0.333131]]) 11 12print([np.where((x_old[:,i].min() > x_new[:,i]) | (x_old[:,i].max() < x_new[:,i])) for i in range(x_old.shape[1])]) 13# [(array([1], dtype=int64),), (array([0], dtype=int64),), (array([0, 2], dtype=int64),)] 14# 0列目の1行目, 1列目の0行目, 2列目の0, 2行目

投稿2021/07/29 05:45

jeanbiego

総合スコア3966

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

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

mini1988

2021/07/29 06:01

ありがとうございます。 それで得られた結果を以下のように表示させるにはどうすればよいでしょうか? 0行目: 1列目,2列目 1行目: 0列目 2行目: 2列目
mini1988

2021/07/29 08:02

ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問