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

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

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

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

pandas

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

Q&A

解決済

2回答

232閲覧

PythonでCSVファイル内のデータ操作を行いたい

mitty.mn

総合スコア12

Python 3.x

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

pandas

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

0グッド

0クリップ

投稿2024/03/31 10:12

実現したいこと

CSVファイルのデータを下記の内容で処理させたい。

  • リスト同じ取引番号のデータごとで処理をさせたい。
  • 取引区分が0で1行のみの時は取引区分が2の行の明細1から明細3までを取引区分が0の明細1から明細3に張り付ける。
  • 同じ取引番号で取引区分が0が複数行あるときは取引区分2の行の入金金額から明細3までを取引区分が0の行に張り付ける。
  • 取引区分に21が入っている行は削除

CSVデータは下記の図のように処理をさせたいです。
イメージ説明

前提

Python(python-3.12.2)でCSVデータを処理するプログラムを作っています。
描いている結果が得られなくて詰まっています。
コードについてアドバイスをいただければと思います。
よろしくお願いいたします。

CSVファイルの中身です。
取引番号,取引トランザクション,取引区分,価格,入金金額,明細1,明細2,明細3
1,1,3,0,,,,
2,2,0,1000,,,,
2,3,2,0,,商品A,カテゴリA,10kg
3,4,0,1000,,,,
3,5,0,1000,,,,
3,6,0,1000,,,,
3,7,2,0,3000,商品B,カテゴリB,500kg
4,8,0,1000,,,,
4,9,0,1000,,,,
4,10,0,1000,,,,
4,11,0,1000,,,,
4,12,0,1000,,,,
4,13,2,0,5000,商品C,カテゴリC,90kg
5,14,0,1000,,,,
5,15,21,0,,,,
5,16,2,0,,,,

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

思い描く集計ができません。
イメージ説明

該当のソースコード

Python

1import pandas as pd 2 3df = pd.read_csv('datafile.csv', encoding='cp932') 4 5df = df[(df['取引区分'] != 21) & (df['取引区分'] != 3)].reset_index(drop=True) 6 7 8# 取引番号でグループ化する 9for _, group in df.groupby('取引番号'): 10 # グループ内の最後の行を取得 11 last_row = group.iloc[-1] 12# 明細1明細2明細3のコピー処理。逆順処理 13for index in group.index[::-1]: 14 15 next_col_index = df.columns.get_loc('明細3') + 1 16 if next_col_index < len(df.columns): # 'マルチ決済金額'の次の列が存在する場合 17 next_col_name = df.columns[next_col_index] 18 df.loc[index, '入金金額':next_col_name] = last_row['入金金額':'明細3'] 19 else: # 'マルチ決済金額'が最後の列の場合 20 df.loc[index, '入金金額':] = last_row['入金金額':'明細3'] 21 22# 変更を加えたデータフレームを新しいCSVファイルとして保存 23df.to_csv('updated_datafile.csv', index=False)

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2024/03/31 10:19 編集

・画像の1枚目と2枚目の内容に齟齬があります。正しい情報を記載してください。 ・取引区分「0」「2」「21」以外のデータはどう扱うのか明示してください。(画像1枚目では2行目の取引区分「3」のデータは削除されているように見えますが、質問文自体には何も書いてありません) ・同一取引番号内に、必ず「取引区分0が1つ以上存在し、取引区分2は1つだけ存在する」と考えてよいのか?
mitty.mn

2024/03/31 10:38

コメントありがとうございます。 ・画像の1枚目と2枚目の内容に齟齬があります。正しい情報を記載してください。 ↓ 画像の一枚目「実現したいこと」の項目に添付している画像は実現したい集計になります。 2枚目の画像「発生している問題・エラーメッセージ」の項目に添付している画像は「該当のソースコード」のコードを実行した結果になります。 説明できておらずすみません。 ・取引区分「0」「2」「21」以外のデータはどう扱うのか明示してください。(画像1枚目では2行目の取引区分「3」のデータは削除されているように見えますが、質問文自体には何も書いてありません) ↓ 取引区分「3」のデータは削除します。その他の数字が出てきた時も削除を行います。 ・同一取引番号内に、必ず「取引区分0が1つ以上存在し、取引区分2は1つだけ存在する」と考えてよいのか? ↓ 1行目のように「0」以外の数字が入っている取引番号が1行分のときがあります。このパターン以外は「取引区分0が1つ以上存在し、取引区分2は1つだけ存在します」
guest

回答2

0

もし、記載いただいたプログラムの通りならインデントの問題と取引区分が2の行を削除していないからではないですか?

python

1import pandas as pd 2df = pd.read_csv('datafile.csv', encoding='utf-8') 3df = df[(df['取引区分'] != 21) & (df['取引区分'] != 3)].reset_index(drop=True) 4for _, group in df.groupby('取引番号'): 5 last_row = group.iloc[-1] 6 for index in group.index[::-1]: 7 next_col_index = df.columns.get_loc('明細3') + 1 8 if next_col_index < len(df.columns): # 'マルチ決済金額'の次の列が存在する場合 9 next_col_name = df.columns[next_col_index] 10 df.loc[index, '入金金額':next_col_name] = last_row['入金金額':'明細3'] 11 else: # 'マルチ決済金額'が最後の列の場合 12 df.loc[index, '入金金額':] = last_row['入金金額':'明細3'] 13df = df[df['取引区分'] != 2] 14# 変更を加えたデータフレームを新しいCSVファイルとして保存 15df.to_csv('updated_datafile.csv', index=False)

イメージ説明

投稿2024/03/31 12:31

aoihello

総合スコア31

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

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

mitty.mn

2024/03/31 13:19

ご回答、誠にありがとうございます。 コード修正して試してみます!
guest

0

ベストアンサー

bfill() して最後の行(取引区分 2)を削除します。

python

1import pandas as pd 2 3df = pd.read_csv('datafile.csv', encoding='cp932') 4df = df[(df['取引区分'] != 21) & (df['取引区分'] != 3)].reset_index(drop=True) 5 6# 7dfx = df.copy() 8cols = ['入金金額','明細1','明細2','明細3'] 9dfx[cols] = dfx.sort_values(['取引番号', '取引区分']).groupby('取引番号')[cols].bfill() 10dfx = dfx.drop(dfx.groupby('取引番号').tail(1).index) 11print(dfx)
取引番号取引トランザクション取引区分価格入金金額明細1明細2明細3
2201000nan商品AカテゴリA10kg
34010003000商品BカテゴリB500kg
35010003000商品BカテゴリB500kg
36010003000商品BカテゴリB500kg
48010005000商品CカテゴリC90kg
49010005000商品CカテゴリC90kg
410010005000商品CカテゴリC90kg
411010005000商品CカテゴリC90kg
412010005000商品CカテゴリC90kg
51401000nannannannan

投稿2024/03/31 12:00

melian

総合スコア19840

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

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

mitty.mn

2024/03/31 12:20

ご回答、誠にありがとうございます。 このように.groupbyを使えばいいのですね。 実データのcsvファイルでも動作確認いたします。
mitty.mn

2024/03/31 22:23

回答ありがとうございます。 試したところ問題が解決しました! ベストアンサーに選ばせていただきました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問