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

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

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

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

Python

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

pandas

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

Q&A

解決済

2回答

2711閲覧

for文で書かれたデータフレーム処理の高速化

SatokoM

総合スコア4

NumPy

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

Python

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

pandas

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

0グッド

0クリップ

投稿2020/07/16 23:20

前提・実現したいこと

複数のデータフレームを組み合わせて総当たりの新しいデータフレームを作りたいと考えています。
ただ、組み合わせるデータフレームの数が増えると遅くなってしまい困っています。
配列に変換することである程度早くはなったのですが、もう少し処理速度を上げたいです。
そもそも書き方が冗長な気がするのでもっとスマートに書きたいです。
よろしくお願いいたします。

該当のソースコード

Python

1import pandas as pd 2import numpy as np 3 4#listを4種類作る 5l_1 = [[1, 2], [3, 4]] 6l_2 = [[11, 22], [33, 44]] 7l_3 = [[111, 222], [333, 444]] 8l_4 = [[1111, 2222], [3333, 4444]] 9 10listからDFに変換 11df1 = pd.DataFrame(l_1, columns=['A', 'B']) 12df2 = pd.DataFrame(l_2, columns=['C', 'D']) 13df3 = pd.DataFrame(l_3, columns=['E', 'F']) 14df4 = pd.DataFrame(l_4, columns=['G', 'H']) 15 16#DFから配列に変換 17array1 = df1.values 18array2 = df2.values 19array3 = df3.values 20array4 = df4.values 21 22#for文を使ってDFを総当たりで結合 23lst = [] 24for I in array1: 25 for I2 in array2: 26 for I3 in array3: 27 for I4 in array4: 28 lst.append(np.concatenate([I, I2, I3, I4])) 29array_merged = np.array(lst) 30array_merged 31 32#カラム名を設定 33columns_name = df1.columns.append(df2.columns) 34columns_name = columns_name.append(df3.columns) 35columns_name = columns_name.append(df4.columns) 36#columns_name = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'] 37 38df_merged = pd.DataFrame(array_merged, columns=columns_name) 39df_merged 40 41 A B C D E F G H 420 1 2 11 22 111 222 1111 2222 431 1 2 11 22 111 222 3333 4444 442 1 2 11 22 333 444 1111 2222 453 1 2 11 22 333 444 3333 4444 464 1 2 33 44 111 222 1111 2222 475 1 2 33 44 111 222 3333 4444 486 1 2 33 44 333 444 1111 2222 497 1 2 33 44 333 444 3333 4444 508 3 4 11 22 111 222 1111 2222 519 3 4 11 22 111 222 3333 4444 5210 3 4 11 22 333 444 1111 2222 5311 3 4 11 22 333 444 3333 4444 5412 3 4 33 44 111 222 1111 2222 5513 3 4 33 44 111 222 3333 4444 5614 3 4 33 44 333 444 1111 2222 5715 3 4 33 44 333 444 3333 4444 5859

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

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

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

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

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

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

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

guest

回答2

0

速度アップが見込まれるかは分かりませんがitertools.productを使うと簡潔に書けます。

Python

1import pandas as pd 2import itertools 3from functools import reduce 4from operator import add 5 6#listを4種類作る 7l_1 = [[1, 2], [3, 4]] 8l_2 = [[11, 22], [33, 44]] 9l_3 = [[111, 222], [333, 444]] 10l_4 = [[1111, 2222], [3333, 4444]] 11 12lst = [] 13for e in itertools.product(l_1, l_2, l_3, l_4): 14 lst.append( reduce(add, e)) 15df = pd.DataFrame(lst, columns=list('ABCDEFGH')) 16print(df)

投稿2020/07/17 00:08

can110

総合スコア38266

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

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

SatokoM

2020/07/17 00:26 編集

ご回答いただきありがとうございます。 今回例のDFを作るためにlist→DFの処理を行っていますが、実際のデータではlistの状態は存在せず、 csvファイルの表から直接DFを作っています。 もしdf1, 2, 3 ,4 を使って作る方法があればご教示いただけますと幸いです。 説明が不十分で申し訳ありません。
can110

2020/07/17 00:41

すでにDFがあれば、それをnumpyのarrayにして.tolistでリストにすればよいです。 すなわち質問コードに合わせれば 「for e in itertools.product(array1.tolist(), array2.tolist(), array3.tolist(), array4.tolist()):」 とすればよいです。
SatokoM

2020/07/22 02:33

そうですね! 考えが及ばなかったです。 ありがとうございます。
guest

0

ベストアンサー

コードを整理すればもっといい方法があるかもしれませんが、以下の方法でいかがでしょうか。itertools.productより速いと思われます(特に各要素が数値なら)。

python

1from sklearn.utils.extmath import cartesian 2 3 4def df_product(df_list): 5 arrs = [df.to_numpy() for df in df_list] 6 lens = np.array([len(arr) for arr in arrs]) 7 8 idx = cartesian([np.arange(length) for length in lens]) 9 offset = lens.cumsum() - lens 10 11 new_arr = np.vstack(arrs)[idx+offset].reshape(-1, 2*len(df_list)) 12 return pd.DataFrame(new_arr, columns=np.concatenate( 13 [df.columns.to_numpy() for df in df_list]))

動作確認

python

1In [11]: l_1 = [[1, 2], [3, 4]] 2 : l_2 = [[11, 22], [33, 44]] 3 : l_3 = [[111, 222], [333, 444]] 4 : l_4 = [[1111, 2222], [3333, 4444]] 5 : 6 : df1 = pd.DataFrame(l_1, columns=['A', 'B']) 7 : df2 = pd.DataFrame(l_2, columns=['C', 'D']) 8 : df3 = pd.DataFrame(l_3, columns=['E', 'F']) 9 : df4 = pd.DataFrame(l_4, columns=['G', 'H']) 10 : 11 : df_product([df1, df2, df3, df4]) 12Out[11]: 13 A B C D E F G H 140 1 2 11 22 111 222 1111 2222 151 1 2 11 22 111 222 3333 4444 162 1 2 11 22 333 444 1111 2222 173 1 2 11 22 333 444 3333 4444 184 1 2 33 44 111 222 1111 2222 195 1 2 33 44 111 222 3333 4444 206 1 2 33 44 333 444 1111 2222 217 1 2 33 44 333 444 3333 4444 228 3 4 11 22 111 222 1111 2222 239 3 4 11 22 111 222 3333 4444 2410 3 4 11 22 333 444 1111 2222 2511 3 4 11 22 333 444 3333 4444 2612 3 4 33 44 111 222 1111 2222 2713 3 4 33 44 111 222 3333 4444 2814 3 4 33 44 333 444 1111 2222 2915 3 4 33 44 333 444 3333 4444

↓数が増えても大丈夫です。

python

1In [12]: l_1 = [[1, 2], [3, 4], [5, 6]] # ←[5, 6]を追加 2 : l_2 = [[11, 22], [33, 44]] 3 : l_3 = [[111, 222], [333, 444]] 4 : l_4 = [[1111, 2222], [3333, 4444]] 5 : 6 : df1 = pd.DataFrame(l_1, columns=['A', 'B']) 7 : df2 = pd.DataFrame(l_2, columns=['C', 'D']) 8 : df3 = pd.DataFrame(l_3, columns=['E', 'F']) 9 : df4 = pd.DataFrame(l_4, columns=['G', 'H']) 10 : 11 : df_product([df1, df2, df3, df4]) 12Out[12]: 13 A B C D E F G H 140 1 2 11 22 111 222 1111 2222 151 1 2 11 22 111 222 3333 4444 162 1 2 11 22 333 444 1111 2222 17# (中略) 1813 3 4 33 44 111 222 3333 4444 1914 3 4 33 44 333 444 1111 2222 2015 3 4 33 44 333 444 3333 4444 2116 5 6 11 22 111 222 1111 2222 2217 5 6 11 22 111 222 3333 4444 2318 5 6 11 22 333 444 1111 2222 2419 5 6 11 22 333 444 3333 4444 2520 5 6 33 44 111 222 1111 2222 2621 5 6 33 44 111 222 3333 4444 2722 5 6 33 44 333 444 1111 2222 2823 5 6 33 44 333 444 3333 4444 29 30In [13]: l_1 = [[1, 2], [3, 4]] 31 : l_2 = [[11, 22], [33, 44]] 32 : l_3 = [[111, 222], [333, 444]] 33 : l_4 = [[1111, 2222], [3333, 4444]] 34 : l_5 = [[11111, 22222], [33333, 44444]] # ←l_5を追加 35 : 36 : df1 = pd.DataFrame(l_1, columns=['A', 'B']) 37 : df2 = pd.DataFrame(l_2, columns=['C', 'D']) 38 : df3 = pd.DataFrame(l_3, columns=['E', 'F']) 39 : df4 = pd.DataFrame(l_4, columns=['G', 'H']) 40 : df5 = pd.DataFrame(l_5, columns=['I', 'J']) 41 : 42 : df_product([df1, df2, df3, df4, df5]) 43Out[13]: 44 A B C D E F G H I J 450 1 2 11 22 111 222 1111 2222 11111 22222 461 1 2 11 22 111 222 1111 2222 33333 44444 472 1 2 11 22 111 222 3333 4444 11111 22222 483 1 2 11 22 111 222 3333 4444 33333 44444 494 1 2 11 22 333 444 1111 2222 11111 22222 505 1 2 11 22 333 444 1111 2222 33333 44444 516 1 2 11 22 333 444 3333 4444 11111 22222 527 1 2 11 22 333 444 3333 4444 33333 44444 538 1 2 33 44 111 222 1111 2222 11111 22222 54# (後略)

速度比較

python

1In [21]: def df_product_itertools(df_list): 2 : lsts = [df.to_numpy().tolist() for df in df_list] 3 : new_list = [reduce(add, e) for e in itertools.product(*lsts)] 4 : return pd.DataFrame(new_list, columns=np.concatenate( 5 : [df.columns.to_numpy() for df in df_list])) 6 7In [22]: l_1 = [[1, 2], [3, 4]] 8 : l_2 = [[11, 22], [33, 44]] 9 : l_3 = [[111, 222], [333, 444]] 10 : l_4 = [[1111, 2222], [3333, 4444]] 11 : l_5 = [[11111, 22222], [33333, 44444]] 12 : 13 : df1 = pd.DataFrame(l_1, columns=['A', 'B']) 14 : df2 = pd.DataFrame(l_2, columns=['C', 'D']) 15 : df3 = pd.DataFrame(l_3, columns=['E', 'F']) 16 : df4 = pd.DataFrame(l_4, columns=['G', 'H']) 17 : df5 = pd.DataFrame(l_5, columns=['I', 'J']) 18 19In [23]: %timeit df_product([df1, df2, df3, df4]) 20 : %timeit df_product_itertools([df1, df2, df3, df4]) 21355 µs ± 18.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each) 22928 µs ± 16.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each) 23 24In [24]: %timeit df_product([df1, df2, df3, df4, df5]) 25 : %timeit df_product_itertools([df1, df2, df3, df4, df5]) 26378 µs ± 12.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each) 271.12 ms ± 17.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

投稿2020/07/17 02:42

編集2020/07/17 04:29
kirara0048

総合スコア1399

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

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

SatokoM

2020/07/22 02:35

ご回答いただきありがとうございます。 実データに適用しても十分な高速化が確認できましたのでこちらをベストアンサーとさせていただきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問