🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Python

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

Q&A

解決済

3回答

716閲覧

Python 行の追加と変換

HarumakiTaro

総合スコア6

Python

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

0グッド

0クリップ

投稿2019/10/26 14:05

前提・実現したいこと

Python pandasで、

|Index|A|B|C|D|E|
|:--|:--|:--|:--|:--|
|1|NaN|10|NaN|NaN|15|
|2|NaN|NaN|20|NaN|NaN|
|3|30|40|NaN|NaN|10|
|4|NaN|10|NaN|20|NaN|
...

といったデータセットを、

|Index|A|B|C|D|E|Target|
|:--|:--|:--|:--|:--|:--|
|1|0|1|0|0|0|10|
|1|0|0|0|0|1|15|
|2|0|0|1|0|0|20|
|3|1|0|0|0|0|30|
|3|0|1|0|0|0|40|
|3|0|0|0|0|1|10|
|4|0|1|0|0|0|10|
|4|0|0|0|1|0|20|
...

のように変換したいです。

ルールは、
・A~E列で数字が入っているところを1、NaNのところは0に変換して、新たに追加されたTarget列に入っている数字をコピーする
・ただし、同じ行内に二つ以上数字が入っている場合は、行を複数行に分けて別々に数字をTarget列に記載する(同じ行内に入っている数字の数だけ新たに行を追加し、A~E列で1は一つだけ、他は0にする)

どなたかお分かりの方がいらっしゃいましたら、よろしくお願いします。

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

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

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

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

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

guest

回答3

0

あまりスマートではありませんが、以下のようにして実装できます。
アイデアとしては、
(1) DFを考えうる最大の行数になるまで複製(やりたいことは、すべてのセルがnanではない場合、行数×列数の行数をもつデータフレームができあがるはず。)
(2) 各行の対象の値がnanであったらいらないので削除する。残った行が必要な行。
(3) 残った行のnanと関係のない値の列を0に、対象の値の列を1に変換
(4) Target列に対象の値を順次格納

python

1# ライブラリ 2import numpy as np 3import pandas as pd 4 5# input 6df = pd.DataFrame(np.array([ 7 [np.nan, 10, np.nan, np.nan, 15], 8 [np.nan, np.nan, 20, np.nan, np.nan], 9 [30, 40, np.nan, np.nan,10], 10 [np.nan, 10, np.nan, 20, np.nan] 11])) 12 13# dfを列数だけコピー 14df = pd.concat([df]*len(df.columns)) 15 16# indexがバラバラなのでソート 17df = df.sort_index() 18 19# ターゲット列を追加 20df['Target'] = np.nan 21 22# 変換処理 23for idx in df.index.unique(): # indexでループ 24 for col in df.columns[:-1]: # Target列以外の列でループ 25 26 # df.loc[idx]は5行5列のdataframe。その対角線をチェックし、nan出ない場合 27 if df.notnull().loc[idx].iloc[col][col]: 28 val = df.loc[idx].iloc[col][col] # 値を保持 29 df.loc[idx].iloc[col] = np.nan # 対象行をすべてnanにする 30 df.loc[idx].iloc[col][col] = 1 # 対象行の値のあった列のみ1に書き換える。 31 df.loc[idx].iloc[col]["Target"] = val # 対象行のTarget列はあった値に設定 32 33# この時点でTarget列がnanの行はいらないのでnanでない行のみ抽出。 34# nanを0に書き換え 35df[df["Target"].notnull()].fillna(0) 36

投稿2019/10/26 15:12

qax

総合スコア622

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

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

HarumakiTaro

2019/10/27 01:29

コード書いていただいてありがとうございました。 手続き的には分かりやすいですね。参考になります。
guest

0

試していないですが自分がすぐ思いつくのは次のような手順です。
多分もっとエレガントなやり方があります。

各列の数値データに列名を付加する
|Index|A|B|C|D|E|
|:--|:--:|--:|--:|--:|
|1|Nan|B10|NaN|NaN|E15|

NaNじゃない要素を抜き出したdataframeを作る。

Target
B10
E15

任意の列を作成し、結合した列名を切り出しセットする。

columnsTarget
B10
E15

pandasのgetdummiesでOne Hot Encodingする。
カラム名を適切な値にリネームする。

投稿2019/10/26 14:31

編集2019/10/26 14:33
pea

総合スコア453

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

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

HarumakiTaro

2019/10/27 01:31

早速のご回答ありがとうございました
guest

0

ベストアンサー

元のテーブルがピボットテーブルっぽかったのでmelt関数で実装してみました。

Python

1import pandas as pd 2import numpy as np 3 4NaN = np.NaN 5 6df = pd.DataFrame( [[ 1, NaN, 10,NaN,NaN, 15], 7 [ 2, NaN,NaN, 20,NaN,NaN], 8 [ 3, 30, 40,NaN,NaN, 10], 9 [ 4, NaN, 10,NaN,NaN,NaN]], 10 columns=[ 'Index', 'A','B','C','D','E' ]) 11 12print(df) 13 14# pivotをlistに変更 15df = pd.melt(df, id_vars=['Index']) 16 17# データの無い行を削除 18df = df.dropna(subset=['value']) 19 20# A~E列を追加 21df = df.assign(A=0, B=0, C=0, D=0, E=0) 22 23# 対応列に1を設定 24for index, row in df.iterrows(): 25 df.loc[index, row['variable']] = 1 26 27#不要列削除&並べ替え&名前変更&並べ替えとか 28df = df.loc[:,['Index','A','B','C','D','E','value']].rename(columns={'value':'Target'}).sort_values('Index').reset_index(drop=True) 29 30print(df) 31

投稿2019/10/26 15:46

編集2019/10/26 16:13
nomuken

総合スコア1627

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

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

HarumakiTaro

2019/10/27 01:27

最近Pythonはじめたばかりのど素人でして、melt関数というを知りませんでした。 forループも一重ですのでスピードも期待できそうですね。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問