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

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

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

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

pandas

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

Q&A

解決済

2回答

2532閲覧

複数行のヘッダがあるデータを縦持ち(Long)に変換したい。

H.K2

総合スコア88

Python 3.x

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

pandas

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

0グッド

0クリップ

投稿2021/08/29 06:51

前提・実現したいこと

下記の図のように、Excelから読み込んだ、複数列にまたがってヘッダが存在するデータを、
縦持ちに変換したいと考えています。
イメージ説明
やり方を調べていると、meltを使うと実現できそうなので、参考URLをもとに、meltを実施したのですが、下記エラーが出てしまいました。下記2点についてご教示いただけましたら幸甚です。

①下記コードのどこがまずいのかご教示いただけないでしょうか。
(エラーコードを見る限り、A_Processのキーが見つけられないように見えるのですが、指定に問題があるのでしょうか。データの渡し方などに問題あり?)
②複数列にまたがるデータを縦持ちに変換するシンプルで一般的な方法があれば(メソッド化できる?)
ご教示いただけますでしょうか。

発生している問題・エラーメッセージ

KeyError: 'A_process' --------------------------------------------------------------------------- KeyError Traceback (most recent call last) ~\AppData\Local\Temp/ipykernel_28196/3457535453.py in <module> ----> 1 df = df.melt( 2 id_vars=id_vars, 3 value_vars=value_vars, 4 ) ~\AppData\Local\Programs\Python\Python39\lib\site-packages\pandas\core\frame.py in melt(self, id_vars, value_vars, var_name, value_name, col_level, ignore_index) 8333 ) -> DataFrame: 8334 -> 8335 return melt( 8336 self, 8337 id_vars=id_vars, ~\AppData\Local\Programs\Python\Python39\lib\site-packages\pandas\core\reshape\melt.py in melt(frame, id_vars, value_vars, var_name, value_name, col_level, ignore_index) 135 mdata = {} 136 for col in id_vars: --> 137 id_data = frame.pop(col) 138 if is_extension_array_dtype(id_data): 139 id_data = cast("Series", concat([id_data] * K, ignore_index=True)) ~\AppData\Local\Programs\Python\Python39\lib\site-packages\pandas\core\frame.py in pop(self, item) 5219 3 monkey NaN 5220 """ -> 5221 return super().pop(item=item) 5222 5223 @doc(NDFrame.replace, **_shared_doc_kwargs) ~\AppData\Local\Programs\Python\Python39\lib\site-packages\pandas\core\generic.py in pop(self, item) 865 866 def pop(self, item: Hashable) -> Series | Any: --> 867 result = self[item] 868 del self[item] 869 ~\AppData\Local\Programs\Python\Python39\lib\site-packages\pandas\core\frame.py in __getitem__(self, key) 3452 if is_single_key: 3453 if self.columns.nlevels > 1: -> 3454 return self._getitem_multilevel(key) 3455 indexer = self.columns.get_loc(key) 3456 if is_integer(indexer): ~\AppData\Local\Programs\Python\Python39\lib\site-packages\pandas\core\frame.py in _getitem_multilevel(self, key) 3503 def _getitem_multilevel(self, key): 3504 # self.columns is a MultiIndex -> 3505 loc = self.columns.get_loc(key) 3506 if isinstance(loc, (slice, np.ndarray)): 3507 new_columns = self.columns[loc] ~\AppData\Local\Programs\Python\Python39\lib\site-packages\pandas\core\indexes\multi.py in get_loc(self, key, method) 2920 2921 if not isinstance(key, tuple): -> 2922 loc = self._get_level_indexer(key, level=0) 2923 return _maybe_to_slice(loc) 2924 ~\AppData\Local\Programs\Python\Python39\lib\site-packages\pandas\core\indexes\multi.py in _get_level_indexer(self, key, level, indexer) 3221 if start == end: 3222 # The label is present in self.levels[level] but unused: -> 3223 raise KeyError(key) 3224 return slice(start, end) 3225 KeyError: 'A_process'

該当のソースコード

Python3

1import pandas as pd 2df = pd.read_excel("test_viz_proj.xlsx", header=[0,1]) 3 4# 縦持ち変換 5id_vars = ["A_process", "B_process", "C_process"] 6value_vars = ["頁数", "指摘件数", "項目数", "NG数"] 7 8df = df.melt( 9 id_vars=id_vars, 10 value_vars=value_vars, 11)

試したこと

複数行の横持データを縦持ちデータに変換するための方法を調査した。

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

python 3.9.6
pandas 1.3.0

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

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

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

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

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

guest

回答2

0

今回のケースだと、やりたいこととpandas.meltでできることがマッチしていないです。
DataFrame.stack()が、やりたいことそのものの機能なので、それを使います。

stackさせない列(今回はProjectの列)をインデックスにしておいてから、
デフォルトでは一番下側の項目をstackするので、level=0で一番上の項目でstackさせます。

python

1import pandas as pd 2 3df = pd.read_excel("test_viz_proj.xlsx", header=[0, 1]) 4 5# 縦持ち変換 6df = df.set_index(df.columns[0]).stack(level=0) 7 8# 列名変更と並び替え 9df = df.rename_axis(index=['Project', 'process']) 10df = df[['頁数', '指摘件数', '項目数', 'NG数']].reset_index()

投稿2021/08/30 00:49

bsdfan

総合スコア4920

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

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

H.K2

2021/09/01 06:12

ご回答ありがとうございます。stack()を使うのですね。やってみます。勉強になりました。
guest

0

ベストアンサー

スマートではありませんが、一応以下でできています。

python

1>>> import pandas as pd 2>>> df = pd.read_excel("test_viz_proj.xlsx", header=[0,1], index_col=0) 3>>> df2 = df.stack().stack().reset_index() 4>>> df2.rename(columns = {'level_0': 'Project', 'Project': 'c', 'level_2': 'process'}, inplace=True) 5>>> df3 = df2.set_index(['Project', 'process']) 6>>> df4 = df3.pivot(columns='c') 7>>> df4.columns = df4.columns.droplevel(0) 8>>> df5 = df4.reset_index() 9>>> df6 = df5[['Project', 'process', '頁数', '指摘件数', '項目数', 'NG数']] 10>>> print(df6) 11c Project process 頁数 指摘件数 項目数 NG数 120 XXX開発 A_process 669.0 36.0 NaN NaN 131 XXX開発 B_process 482.0 56.0 NaN NaN 142 XXX開発 C_process 467.0 85.0 32.0 1.0 153 YYY開発 A_process 356.0 66.0 NaN NaN 164 YYY開発 B_process 927.0 80.0 NaN NaN 175 YYY開発 C_process 10.0 31.0 149.0 17.0 186 ZZZ開発 A_process 903.0 312.0 NaN NaN 197 ZZZ開発 B_process 860.0 35.0 NaN NaN 208 ZZZ開発 C_process 424.0 42.0 525.0 45.0

投稿2021/08/29 08:53

ppaul

総合スコア24672

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

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

H.K2

2021/08/29 23:19 編集

ご回答ありがとうございます!stack()というのは、列のデータを行にピポッド(?)させるようなイメージの処理のようなのですが、index_col=0を指定してあげないときちんと動かないのでしょうか。 また、このコードだと2階層の場合はできそうに思うのですが、n階層のように一般化することは難しいでしょうか。(stackを、階層分コールする?実務では、この部分がたまに3階層、4階層のものが出てきてしまっています…)
ppaul

2021/08/30 00:49

- index_col=0を指定してあげないときちんと動かないのでしょうか。 指定せずに動くようなコードも作れますが、今回の回答のコードよりもさらに複雑になります。 その理由は、Projectの列だけが1階層で、他の列は2階層だからです。 - n階層のように一般化することは難しいでしょうか。 入力データが1階層と2階層と3階層が混在しているとかだと一般化はむずかしいでしょう。 どういう入力があって、どういう出力を出したいかのパターンが100種類とかあるようなら、それを記述する方式を考えてそれに沿って処理することになりとても大変です。プロであっても1千万円以下で受けるとは思えません。 入力と出力のパターンが10通り以下なら、それぞれの処理をするコードを10通り書けば良いので勉強すればできるようにはなるでしょう。
H.K2

2021/09/01 06:10

ご指摘ありがとうございます。この問題とは別の問題があるようですので、複合パターンを明確にして考えてみます。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.30%

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

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

質問する

関連した質問