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

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

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

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

Q&A

解決済

2回答

529閲覧

縦持ちの表形式のデータを高速で横持ちのnumpy配列にしたい

iMasa

総合スコア22

Python

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

0グッド

3クリップ

投稿2019/01/22 21:20

編集2019/01/23 22:20

困っていること

下記のような処理をおよそ1万回実行する必要があり、高速化を検討しています。
並列化も検討できるのですが、まずは素直に処理方法を見直すことで高速化できる知恵を頂きたいです。

やりたいこと

ソースコードに記載している通りITEMとその数値を保持している表形式の元データがあります。
その元データに対して、

数値を1件単位に分割したうえで横持ちのNUMPY配列にしたいです

データフレーム等を使わなければ高速化できるのか?などを試行錯誤中です。
ソースコードはそのまま実行できるように記述しています。

元データ:dict_arr
変換後のデータ:ndarr
期待する結果

print(ndarr) #[[1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1] # [0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0] # [0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0]]

ソースコード

import pandas as pd import numpy as np dict_arr = {'ITEM':["A","B","C","A"],'NUM':[4,5,6,2]} df = pd.DataFrame(dict_arr) df2 = pd.DataFrame(data=None, columns=df.columns) for idx, row in df.iterrows(): for i in range(row['NUM']): df2 = df2.append(row) df2.reset_index(inplace=True) df2['COL'] = df2.index df2['ONE'] = 1 df2_piv = pd.pivot_table(df2, index=['ITEM'], columns='COL', values='ONE',fill_value=0, aggfunc=np.sum).reset_index() df2_piv.sort_values('ITEM',inplace=True) df2_piv.drop(columns=['ITEM'], axis=1, inplace=True) ndarr = df2_piv.values

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

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

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

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

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

mather

2019/01/23 02:29 編集

> 数値を1件単位に分割したうえで横持ちのNUMPY配列にしたいです という内容がわかりにくいので、期待値である ndarr の内容を質問に記載したほうがいいと思います。 わざわざ実行しないと期待値がわからないのは面倒です。
iMasa

2019/01/23 22:32

修正しました。 確かにおっしゃる通りです。 ご指摘ありがとうございました。
guest

回答2

0

ベストアンサー

python

1import pandas as pd 2import numpy as np 3 4dict_arr = {'ITEM':["A","B","C","A"],'NUM':[4,5,6,2]} 5 6data = np.array([x for i, n in 7 zip(dict_arr["ITEM"], dict_arr["NUM"]) 8 for x in [i]*n]) 9idx = np.unique(dict_arr["ITEM"]) 10ndarr = np.zeros((len(idx), len(data)), dtype=int) 11 12for i, x in enumerate(idx): 13 ndarr[i, data==x] = 1 14 15print(ndarr)

質問文のデータではオリジナルの3桁倍速かったけど、より大きいデータでスケールするかは確認していません。というか無駄が多いのでもう少し良い方法があると思う。

投稿2019/01/23 02:46

編集2019/01/23 02:56
hayataka2049

総合スコア30933

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

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

iMasa

2019/01/23 11:29

回答ありがとうございます。 よりシンプルな記述の方をベストアンサーにさせて頂きました。 速度比較をさせて頂きます。
iMasa

2019/01/23 22:35 編集

こちらの方が速度がでましたのでベストアンサーとさせて頂きました。 無駄が多いのは間違いありません。 今はプログラミング力の高いエンジニアが不足している、かつ開発を依頼する業務担当の私もシステムに関する理解が低い状況です。 そのため要件もはじめからFIXさせることも難しく、外注すると膨大な費用がかかります。なので少しでも自分で・・・と思い努力しています。 このようなスポット解決の相談に乗っていただけるのは非常に助かります。
guest

0

とりあえず、現在行っている処理は、下記のようにかなりシンプルに書けそうです。これで処理時間は 1/10 くらいになります。

Python

1import pandas as pd 2import numpy as np 3dict_arr = {'ITEM':["A","B","C","A"],'NUM':[4,5,6,2]} 4df = pd.DataFrame(dict_arr) 5 6df2 = df.apply(lambda d: pd.Series([d['ITEM']]*d['NUM']), axis=1).stack() 7ndarr = pd.get_dummies(df2).values.T 8print(ndarr) 9#[[1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1] 10# [0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0] 11# [0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0]]

投稿2019/01/22 23:41

magichan

総合スコア15898

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

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

iMasa

2019/01/23 11:28 編集

お二方に頂いた双方をためして勉強したいと思います。 回答ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問