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

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

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

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

Q&A

解決済

1回答

570閲覧

Pandasでunstackの列名の指定の仕方、0の場合の列追加方法

barobaro

総合スコア1286

pandas

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

0グッド

0クリップ

投稿2020/08/11 15:41

前提・実現したいこと

この表から括弧内の数値を分離して
例 16(1)の場合16をXXXの列、(1)をYYYの列に振り分け

日付AAABBBCCC合計
8月5日16(1)36355(1)
8月6日1130(1)849(1)
8月7日28(1)331374(1)
8月8日1510227
8月9日5005
8月10日4004

下記のような図を作成したいのですが

AAAAAABBBBBBCCCCCC合計合計
日付XXXYYYXXXYYYXXXYYYXXXYYY
8月5日16136030551
8月6日11030180491
8月7日281330130741
8月8日15010020270
8月9日50000050
8月10日40000040

試したことのようにcolumnsを直接指定ではなく
データによりcolumnsが変わるため自動で設定したい
CCC-YYYのように0の場合の列追加方法を教えてください
よろしくお願いします

該当のソースコード

python

1import io 2import pandas as pd 3 4data = """\ 5日付,AAA,BBB,CCC,合計 68月5日,16(1),36,3,55(1) 78月6日,11,30(1),8,49(1) 88月7日,28(1),33,13,74(1) 98月8日,15,10,2,27 108月9日,5,0,0,5 118月10日,4,0,0,4 12""" 13df = pd.read_csv(io.StringIO(data), index_col=0) 14dfs = [items.astype(str).str.extractall("([0-9,]+)").unstack(fill_value=0) for label, items in df.iteritems()] 15 16df1 = pd.concat(dfs, axis=1) 17df1

試したこと

python

1arrays = [["AAA", "AAA", "BBB", "BBB", "CCC", "合計", "合計"], ["XXX", "YYY", "XXX", "YYY", "XXX", "XXX", "YYY"]] 2tuples = list(zip(*arrays)) 3df1.columns = pd.MultiIndex.from_tuples(tuples)

CCC-YYY列がない

AAAAAABBBBBBCCC合計合計
日付XXXYYYXXXYYYXXXXXXYYY
8月10日4000040
8月5日1613603551
8月6日1103018491
8月7日28133013741
8月8日1501002270
8月9日5000050

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

Pandas1.1

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

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

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

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

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

guest

回答1

0

ベストアンサー

結合してからunstack()を使ってはどうでしょうか。

python

1dfs = [items.astype(str).str.extractall("([0-9,]+)") 2 for label, items in df.iteritems()] 3 4df1 = (pd.concat(dfs, axis=1).set_axis(df.columns, axis=1) 5 .rename(index={0: 'XXX', 1: 'YYY'}, level=1) 6 .unstack().fillna(0).astype(int)) 7 8df1 9# AAA BBB CCC 合計 10# match XXX YYY XXX YYY XXX YYY XXX YYY 11# 日付 12# 8月10日 4 0 0 0 0 0 4 0 13# 8月5日 16 1 36 0 3 0 55 1 14# 8月6日 11 0 30 1 8 0 49 1 15# 8月7日 28 1 33 0 13 0 74 1 16# 8月8日 15 0 10 0 2 0 27 0 17# 8月9日 5 0 0 0 0 0 5 0

実際のところはリストにしてfor文で要素ごとに処理したほうが楽かつ早いかと思います。

python

1import numpy as np 2 3arr = [] 4for s in df.to_numpy().ravel().tolist(): 5 out = str(s).rstrip(')').split('(') 6 if len(out) == 1: 7 out += ['0'] 8 arr.append(out) 9 10out_df = pd.DataFrame( 11 np.array(arr, dtype=int).reshape(len(df), -1), 12 index=df.index, 13 columns=pd.MultiIndex.from_product((df.columns, ['XXX', 'YYY']))) 14out_df 15# AAA BBB CCC 合計 16# XXX YYY XXX YYY XXX YYY XXX YYY 17# 日付 18# 8月5日 16 1 36 0 3 0 55 1 19# 8月6日 11 0 30 1 8 0 49 1 20# 8月7日 28 1 33 0 13 0 74 1 21# 8月8日 15 0 10 0 2 0 27 0 22# 8月9日 5 0 0 0 0 0 5 0 23# 8月10日 4 0 0 0 0 0 4 0

投稿2020/08/12 01:39

kirara0048

総合スコア1399

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

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

barobaro

2020/08/12 02:03

kirara0048 さんありがとうございます MultiIndex時のrename方法とset_axisがわかりすごい勉強になりました set_axisを使ったことがなかったのですが サンプルをみて勉強します ありがとうございました
barobaro

2020/08/12 02:29

質問大丈夫でしょうか? df1 = df1.set_axis(df.columns, axis=1) df1.columns Index(['AAA', 'BBB', 'CCC', '合計'], dtype='object') df.columns Index(['AAA', 'BBB', 'CCC', '合計'], dtype='object') df1.columns == df.columns array([ True, True, True, True]) columnsの結果が同じだったので 試しに df1.colmuns = df.columnsだとエラーがでるのですが /usr/local/lib/python3.6/dist-packages/ipykernel_launcher.py:1: UserWarning: Pandas doesn't allow columns to be created via a new attribute name - see https://pandas.pydata.org/pandas-docs/stable/indexing.html#attribute-access """Entry point for launching an IPython kernel. df1.columns == df.columnsはだめで set_axisはOKなのかわかりましたら教えてもらえますか? set_axisはどういうときに使うのかわかれば教えてください
kirara0048

2020/08/12 02:50

属性(df.XXX)に直接代入すること、つまり「 df.XXX = xxx 」のような書き方はするべきではないということです。 「 df.columns = xxx 」は「 df.set_axis(xxx, axis=1, inplace=True) 」で可能なので、後者を使うようにしてください。
barobaro

2020/08/12 04:21

kirara0048 さん どうもありがとうございます。 df.columns = xxx ばっかりしていましたので今後は df.set_axis(xxx, axis=1, inplace=True) にするようにします
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問