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

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

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

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

データ構造

データ構造とは、データの集まりをコンピュータの中で効果的に扱うために、一定の形式に系統立てて格納する形式を指します。(配列/連想配列/木構造など)

Python

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

pandas

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

Q&A

1回答

1456閲覧

CSVをPythonで集計したいが条件が複雑すぎてわからない

KAZ1009

総合スコア6

CSV

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

データ構造

データ構造とは、データの集まりをコンピュータの中で効果的に扱うために、一定の形式に系統立てて格納する形式を指します。(配列/連想配列/木構造など)

Python

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

pandas

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

0グッド

0クリップ

投稿2021/03/21 09:50

前提・実現したいこと

plan.csvをpandasで集計し、testResult.xlsxへ入力するプログラムを組みたいのですが、集計方法が複雑で全くうまくいきません。
かれこれ一週間近く格闘したのですがあきらめてご質問させていただきます、どうかご教示お願い致します。

'ReservationRouteCode1','PackageCode',"PackageName","RoomType","PersonsPerRoom",'ResultPerson'
plan.csvから上記の列を使用します。
'ReservationRouteCode1'はパッケージコードマスターのエージェントに対応しています。
横の英文字はtestResult.xlsxの入力列です。

各'ReservationRouteCode1'、'PackageCode'ごとにtestResult.xlsxへ入力していきます。
その際入力するのは'ResultPerson'を"PersonsPerRoom"で割ったものになります。
ただし、'ReservationRouteCode1','PackageCode',
"RoomType","PersonsPerRoom"
は事前に合計しておかないと割った際に誤差が出るためgroopbyをしてsum()で処理しています。

ここからが今困っていることなのですが、まずforでエージェントのキーを回し、'ReservationRouteCode1'がそれと合致するものを抜き出す。
その後パッケージコードの辞書もforループさせ、パッケージコードが合致するものを抜き出す。
そしてパッケージコードの利用人数、部屋タイプに関しても記載がある場合に限り、それらも仕分け条件に含める。
部屋タイプに関しては2つ存在する可能性もある。

空のdfを扱おうとするとエラーが出たのでこのような形にしたのですが、今度はdf_boolの値が1つしかない場合にdf_bool.sum()でエラーが出ます。
ここの解消方法もよくわからないのですが、そもそも条件分岐をかいくぐってきているデータがそもそも少なすぎるのですが、その理由もわかりません。

df_bool = (data["PackageCode"] == package_code) if type(df_bool) is bool: if df_bool is False: continue if df_bool.sum() > 0: data = data[data["PackageCode"] == package_code] print(len(data),agent,package_code) else: continue

この部分の処理が間違っていて必要なデータまで弾いてしまっているようですがなぜなのか理解できませんでした。

コメントアウトしている部分はいろいろ試してダメだったうちの一つですので気にしないでください。
まだ勉強を始めたばかりの初心者なので見苦しいコードになっていると思いますがよろしくお願いします。

plan.csv:
https://drive.google.com/file/d/1_9qRc-iTbRwy4QdXyHtLJQIgipeAZnoX/view?usp=sharing

testResult.xlsx:
https://drive.google.com/file/d/1z7miEWQwXnCKVNb9o8bG4GJusZHQfeCD/view?usp=sharing

パッケージコードマスター.xlsx:
https://drive.google.com/file/d/1isAY9OeJpIZNPCXyB2DM7AAT-AWxJRP8/view?usp=sharing

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

AttributeError: 'bool' object has no attribute 'sum'

該当のソースコード

Python3

1# -*- coding: utf-8 -*- 2import pandas as pd 3import openpyxl as xl 4def plan_counter(): 5 df = pd.read_csv("plan.csv" ,usecols=['ReservationRouteCode1', 6 'PackageCode',"PackageName", 7 "RoomType", "PersonsPerRoom", 8 'ResultPerson'], encoding='CP932') 9 df = df.drop(0) 10 df["PersonsPerRoom"] = df["PersonsPerRoom"].astype(int) 11 df['ResultPerson'] = df['ResultPerson'].astype(int) 12 df = df.groupby(by=['ReservationRouteCode1','PackageCode', 13 "PackageName","RoomType", "PersonsPerRoom"]).sum() 14 df = df.reset_index() 15 df['ResultPerson'] = df['ResultPerson'] // df["PersonsPerRoom"] 16 df["PersonsPerRoom"] = df["PersonsPerRoom"].astype(str) 17 return df 18 19def agent_dict(): 20 wb = xl.load_workbook("パッケージコードマスター.xlsx", data_only=True) 21 ws = wb.worksheets[0] 22 target_dict = {} 23 for i in range(2,13): 24 agt_code = ws["G" + str(i)].value 25 agt_cell = ws["H" + str(i)].value 26 target_dict[agt_code] = agt_cell 27 return target_dict 28 29def package_dict(): 30 wb = xl.load_workbook("パッケージコードマスター.xlsx", data_only=True) 31 ws = wb.worksheets[0] 32 target_dict = {} 33 for i in range(5,165): 34 if ws["B" + str(i)].value is not None: 35 package_code = ws["B" + str(i)].value 36 room_cell1 = ws["C" + str(i)].value 37 room_cell2 = ws["D" + str(i)].value 38 people_cell = ws["E" + str(i)].value 39 40 target_dict[i] = [ package_code, 41 room_cell1, room_cell2, 42 people_cell] 43 return target_dict 44 45 46 47 48wb = xl.load_workbook("プラン集計表.xlsx", data_only=True) 49ws = wb.worksheets[0] 50 51 52agent_dict = agent_dict() 53package_dict = package_dict() 54 55df = plan_counter() 56 57for agent in agent_dict.keys(): 58 59 df_bool = (df["ReservationRouteCode1"] == agent) 60 if df_bool.sum() > 0: 61 data = df[df["ReservationRouteCode1"] == agent] 62 else: 63 continue 64 #print(len(data),agent) 65 for i ,j in package_dict.items(): 66 package_code = j[0] 67 room_type1 = j[1] 68 room_type2 = j[2] 69 people = j[3] 70 71 df_bool = (data["PackageCode"] == package_code) 72 if type(df_bool) is bool: 73 if df_bool is False: 74 continue 75 if df_bool.sum() > 0: 76 data = data[data["PackageCode"] == package_code] 77 print(len(data),agent,package_code) 78 else: 79 continue 80 81 df_bool = (data["PersonsPerRoom"] == people) 82 if (df_bool.sum() > 0) and (people is not None): 83 data = data[data["PersonsPerRoom"] == people] 84 85 df_bool = (data["RoomType"] == room_type1) 86 if (df_bool.sum() > 0) and (room_type1 is not None): 87 data = data[data["RoomType"] == room_type1] 88 89 df_bool = (data["RoomType"] == room_type2) 90 if (df_bool.sum() > 0) and (room_type1 is not None): 91 data2 = data[data["RoomType"] == room_type2] 92 data.append(data2) 93 #if package_code in data.values: 94 # data = data[data["PackageCode"] == package_code] 95 # if (people is not None) and (people in data.values): 96 # data = data[data["PersonsPerRoom"] == people] 97 # if (room_type1 is not None) and (room_type1 in data.values): 98 # data2 = data[data["RoomType"] == room_type1] 99 # if (room_type2 is not None) and (room_type2 in data.values): 100 # data2.append(data[data["RoomType"] == room_type2]) 101 # data = data2 102 103 #print() 104 data = data.sum() 105 column = agent_dict[agent] 106 row = i 107 cell = column + str(i) 108 #print(data['ResultPerson']) 109 #ws[cell].value = data['ResultPerson'] 110 111wb.save('testResult.xlsx') 112 113 114

試したこと

ここに問題に対して試したことを記載してください。

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

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

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

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

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

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

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

bsdfan

2021/03/21 12:04

data = data.sum()でいろいろおかしくなっていそうですが、この行は必要ですか?
KAZ1009

2021/03/21 12:19

最終的に求めたいのが仕分けた後に残ったdataframeのResultpersonの合計なのでそのようにしました!
guest

回答1

0

data = data.sum()
で、dataがDataFrame → Seriesに変わります。

なので、内側の(package_dictに対する)ループで、

1回目は
data: DataFrame
→ data["PackageCode"]: Series(=PackageCode列)
→ df_pool: Series

2回目は
data: Series
→ data["PackageCode"]: スカラー(=PackageCode列の文字列を連結したもの)
→ df_pool: ブール値

となります。

そのため、df_pool.sum()で記載のエラーが出ています。

今回の場合、中で使うデータを削っていくようなやり方はわかりにくくなるのではないでしょうか。
条件に合致するしないのブールのSeries(下記のselect)をandやorで更新していって、最後にデータを取り出すのが良いように思います。

python

1for agent in agent_dict.keys(): 2 data = df[df["ReservationRouteCode1"] == agent] 3 if len(data) == 0: 4 continue 5 6 result = [] 7 for j in package_dict.values(): 8 package_code = j[0] 9 room_type1 = j[1] 10 room_type2 = j[2] 11 people = j[3] 12 13 select = (data["PackageCode"] == package_code) 14 if people is not None: 15 select &= (data["PersonsPerRoom"] == people) 16 if room_type1 is not None: 17 room = (data["RoomType"] == room_type1) 18 if room_type2 is not None: 19 room |= (data["RoomType"] == room_type2) 20 select &= room 21 result.append(data[select]) 22 df_result = pd.concat(result) 23 print(agent, df_result['ResultPerson'].sum())

最終的に求めたいのが仕分けた後に残ったdataframeのResultpersonの合計なのでそのようにしました!

やりたいことを完全には理解できていないので、違うかもしれませんが、合計を求めるのは内側のループが全部終わってからやればいいのではないですか?

投稿2021/03/21 23:58

編集2021/03/22 02:39
bsdfan

総合スコア4794

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問