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

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

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

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

pandas

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

Q&A

解決済

1回答

922閲覧

ある一つの列で同じ値を持つもの同士を1行に纏め、また1行にまとめる回数は3回までの制限を与えたい。

shu1_1

総合スコア5

Python 3.x

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

pandas

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

0グッド

0クリップ

投稿2019/08/26 07:35

編集2019/08/26 12:30

現在以下のような内容のcsvファイル「test.csv」があり、

test = pd.read_csv('test.csv', encoding='shift-jis')

ID 売上 地域
1 100 東京
1 110 東京
1 120 東京
1 130 東京
2 90 千葉
2 80 千葉
2 70 千葉
2 60 千葉

このファイルを

・"ID"列に同じ値をもつ行を、元のファイルでの順番を維持したまま3ヶ月前までの売り上げを1行にまとめる
・3ヶ月前の売り上げ情報がない場合はNaNまたは0となるようにする。

といった決まりに従いPythonで加工して、

ID 売上 地域 1ヶ月前売り上げ 2ヶ月前売り上げ 3ヶ月前売り上げ
1 100 東京 110 120 130
1 110 東京 120 130 NaN
1 120 東京 130 NaN NaN
1 130 東京 NaN NaN NaN
2 90 千葉 80 70 60
2 80 千葉 70 60 NaN
2 70 千葉 60 NaN NaN
2 60 千葉 NaN NaN NaN

という内容に変更しtest2.csvファイルを作りたいのですが、
これはどのような処理を書けば実現できるでしょうか。
お手数ですがご教示お願いします。

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

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

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

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

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

guest

回答1

0

ベストアンサー

以下のようにすればよいかと思います。

  1. 行を渡すと、nヶ月前の売上を返す関数を作成する。
  2. DataFrame.apply でその関数を行ごとに適用する。

関数は行ごとに呼び出され、以下のような Series オブジェクトが渡されるので

月 9月 ID 1 売上 100 地域 東京 Name: 0, dtype: object

この行の場合

  1. 9月 - 3ヶ月 = 6月 を計算する。
  2. ID1で6月の行の売上を抽出する。抽出した結果が空の場合、そのようなデータはないということなので、np.nan を返す。

python

1import numpy as np 2import pandas as pd 3 4df = pd.DataFrame( 5 { 6 "月": ["9月", "8月", "7月", "6月", "9月", "8月", "7月", "6月"], 7 "ID": [1, 1, 1, 1, 2, 2, 2, 2], 8 "売上": [100, 110, 120, 130, 90, 80, 70, 60], 9 "地域": ["東京", "東京", "東京", "東京", "千葉", "千葉", "千葉", "千葉"], 10 } 11) 12print(df) 13# 月 ID 売上 地域 14# 0 9月 1 100 東京 15# 1 8月 1 110 東京 16# 2 7月 1 120 東京 17# 3 6月 1 130 東京 18# 4 9月 2 90 千葉 19# 5 8月 2 80 千葉 20# 6 7月 2 70 千葉 21# 7 6月 2 60 千葉 22 23 24def get_n_month_ago(row, n): 25 id_, month = row["ID"], row["月"] 26 27 # nヶ月前を表す文字列を作成する。(例: 9月だったら6月) 28 n_month_ago = str(int(month[:-1]) - i) + "月" 29 30 # 「ID が同じ」かつ「月が n_month_ago」と一致する行の列「売上」の値を取得する。 31 sale_n_month_ago = df.loc[(df["ID"] == id_) & (df["月"] == n_month_ago), "売上"] 32 33 # もしそのような値が存在しない場合は sale_n_month_ago は空なので、NaN とする。 34 # 存在する場合はスカラーにする。 35 sale_n_month_ago = np.nan if sale_n_month_ago.empty else sale_n_month_ago.values[0] 36 37 return sale_n_month_ago 38 39 40for i in range(1, 4): 41 df[f"{i}ヶ月前売り上げ"] = df.apply(get_n_month_ago, axis=1, args=(i,)) 42 43df.to_csv("test2.csv", index=False)

作成された CSV

csv

1月,ID,売上,地域,1ヶ月前売り上げ,2ヶ月前売り上げ,3ヶ月前売り上げ 29月,1,100,東京,110.0,120.0,130.0 38月,1,110,東京,120.0,130.0, 47月,1,120,東京,130.0,, 56月,1,130,東京,,, 69月,2,90,千葉,80.0,70.0,60.0 78月,2,80,千葉,70.0,60.0, 87月,2,70,千葉,60.0,, 96月,2,60,千葉,,,

投稿2019/08/26 10:06

編集2019/08/26 10:14
tiitoi

総合スコア21956

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

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

shu1_1

2019/08/26 12:08

tiitoiさん ご回答ありがとうございます。 希望していた通りの結果が出力されました。 大変助かりました。 また、追加で大変恐縮なのですが 先程の結果をIDのみで実現することは可能でしょうか。 ご回答頂いた ># 「ID が同じ」かつ「月が n_month_ago」と一致する行の列「売上」の値を取得する。 を# 「同じID」と一致する行の列「売上」の値を取得し、先程のtest2.csvと同じ結果を出力したい。 お忙しいとは存じますが、ご教示頂けましたら幸いです。
tiitoi

2019/08/26 12:21

同じIDの行は複数行あると思いますが、どの行の売上を出力するのでしょうか。 質問欄を編集して、処理後の DataFrame のイメージを追記していただけますか。
shu1_1

2019/08/26 12:41

ご指摘ありがとうございます。 質問蘭を編集いたしました。 処理前のDataFrameから"月"を削除しました。 IDのみで処理後の出力結果を得たいのですが可能でしょうか。 質問ばかりで申し訳ございません。
tiitoi

2019/08/26 12:44

> IDのみで処理後の出力結果を得たいのですが可能でしょうか。 それはできないです。 列「月」の情報がないと、各行が何月のデータなのかわからないため、数ヶ月前の売上を探すことはできなくなります。
shu1_1

2019/08/26 12:47

ご回答ありがとうございます。 実現不可である事承知いたしました。 色々とご回答いただき大変助かりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問