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

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

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

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

Python 2.7

Python 2.7は2.xシリーズでは最後のメジャーバージョンです。Python3.1にある機能の多くが含まれています。

Q&A

解決済

2回答

8978閲覧

PythonでGroup ByしてCumsum(累計)したいです

mkobadev1

総合スコア4

NumPy

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

Python 2.7

Python 2.7は2.xシリーズでは最後のメジャーバージョンです。Python3.1にある機能の多くが含まれています。

0グッド

0クリップ

投稿2015/01/16 03:18

2つの同じlengthの配列(Key, value)があります。

lang

1# numpy version is 1.6 2import numpy as np 3key = np.array(["a","a","b","b","b","c","c","c","c"]) 4value = np.array([1,2,3,4,5,6,7,8,9])

valueをkeyでGroup ByしてCumsum(累計)したいです。

期待される結果

lang

1([1,3, 3,7,12, 6,13,21,30])

なるべくfor文を使わず高速で、Pandasも使用しないやり方があれば幸いです。
よろしくお願いいたします。

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

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

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

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

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

guest

回答2

0

ベストアンサー

すごくダサいし、実用プログラムでは絶対にやらないけど。
tmpがすごくカッコ悪くてやっつけ感丸出しですが(笑)

lang

1import numpy as np 2from collections import defaultdict 3 4key = np.array(["a","a","b","b","b","c","c","c","c"]) 5value = np.array([1,2,3,4,5,6,7,8,9]) 6 7dic = defaultdict(list) 8tmp = map(lambda item: dic[item[0]].append(item[1]), zip(key, value)) 9lst = sorted(dic.items(), key=lambda item:item[0]) 10reduce(lambda a, b: np.r_[a,b], map(lambda d:np.cumsum(d[1]), lst), []).astype(np.int)

普通にfor文回したり、リスト内包表記で書いた方が色々な意味で良いと思いますが^^

投稿2015/01/21 06:49

fsoe

総合スコア163

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

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

mkobadev1

2015/01/23 03:32

回答いただいた中で、一番速かったので、ベストアンサーとさせていただきます。
ShinpeiYamamoto

2015/01/24 23:48

ちょっとまってください。 timeitで計測してみましたが、多分私のは内容の確認のためのprint文の分遅くなっているだけですよ。そんなはずない。苦笑(なんだかstackoverflowの解答欄みたいですが。w) それぞれモジュールとしてmain関数の中に実装をいれて計測してみると Type "help", "copyright", "credits" or "license" for more information. >>> import timeit >>> t = timeit.Timer("answer1.main()", "import answer1") #shimpeiyamamoto answer >>> t.timeit(100) 0.007233890339088135 >>> t = timeit.Timer("answer2.main()", "import answer2") #fsoe answer >>> t.timeit(100) 0.03755464856331514 >>> t = timeit.Timer("answer3.main()", "import answer3") #mkobadev1 answer >>> t.timeit(100) 0.03962027967747872 という感じになりました。 ま、私の環境なのでぜひ質問者さんご自身で実行してみてください。 -------answer1.py import numpy as np from itertools import groupby, izip def main(): key = ["a","a","b","b","b","c","c","c","c"] value = [1,2,3,4,5,6,7,8,9] array = np.array([], dtype=np.int32) for key, items in groupby(izip(key, value),lambda i: i[0]): array = np.r_[array, np.array([x[1] for x in list(items)]).cumsum()] ------- -------answer2.py import numpy as np from collections import defaultdict def main(): key = np.array(["a","a","b","b","b","c","c","c","c"]) value = np.array([1,2,3,4,5,6,7,8,9]) dic = defaultdict(list) tmp = map(lambda item: dic[item[0]].append(item[1]), zip(key, value)) lst = sorted(dic.items(), key=lambda item:item[0]) reduce(lambda a, b: np.r_[a,b], map(lambda d:np.cumsum(d[1]), lst), []).astype(np.int) ------- -------answer3.py import numpy as np def main(): key = np.array(["a","a","b","b","b","c","c","c","c"]) value = np.array([1,2,3,4,5,6,7,8,9]) value_ = value[np.argsort(key)] key_ = np.sort(key) u_key_, id_key_ = np.unique(key_, return_inverse=True) d_id_key_ = np.diff(id_key_) pos = np.where(d_id_key_ != 0)[0] + 1 split_value = np.split(value_, pos) cumsum_value = np.array([np.cumsum(data_).astype(np.int) for data_ in split_value]) cumsum_value = np.hstack(cumsum_value) ------- 以上です。
mkobadev1

2015/04/21 05:56

大変失礼いたしました。 一つ確認したいのですが、pythonは3系でしょうか?
guest

0

お邪魔します。

効率のいい方法かどうかわかりませんが、とりあえずやってみました。

lang

1import numpy as np 2from itertools import groupby, izip 3 4key = ["a","a","b","b","b","c","c","c","c"] 5value = [1,2,3,4,5,6,7,8,9] 6 7array = np.array([], dtype=np.int32) 8for key, items in groupby(izip(key, value),lambda i: i[0]): 9 array = np.r_[array, np.array([x[1] for x in list(items)]).cumsum()] 10 11print array 12#array([ 1, 3, 3, 7, 12, 6, 13, 21, 30])

for文を内包表記に書き換えるなどは可能ですが、可読性が下がりすぎるかなと思い取り合えずfor文にしました。グループ化のための引き当て関数を工夫したらもう少しうまい実装があるかとも思ったのですが、とりあえずです。
もうちょっといい方法を思いついたらまた記載しますね。

以上、参考まで。

投稿2015/01/18 15:01

ShinpeiYamamoto

総合スコア540

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

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

mkobadev1

2015/01/20 06:33

可読性はおいておいて、このようなのを考えてみました。 value_ = value[np.argsort(key)] key_ = np.sort(key) u_key_, id_key_ = np.unique(key_, return_inverse=True) d_id_key_ = np.diff(id_key_) pos = np.where(d_id_key_ != 0)[0] + 1 split_value = np.split(value_, pos) cumsum_value = np.array([np.cumsum(data_).astype(np.int) for data_ in split_value]) cumsum_value = np.hstack(cumsum_value) いい方法を思いついたら是非投稿お願いします!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問