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

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

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

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

Q&A

解決済

4回答

917閲覧

groupbyを使った集計

kumer1

総合スコア26

Python

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

0グッド

0クリップ

投稿2019/05/23 14:03

前提・実現したいこと

groupby機能を使って同じキーワードで巻数が付いているのものをまとめたいです。
例えば、このようなCSVがあった場合、

作品名|著者|売上
愛してる(1)|もぎ|100
愛してる(1)|もぎ|200
愛してる(2)|もぎ|300
愛してる(2)|もぎ|400
愛してる(3)|もぎ|500
愛してる(3)|もぎ|600

作品名|著者|売上
愛してる|もぎ|2100

としたいです。

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

ここまではできますがこれ以上はできない。。 作品名|著者|売上 愛してる(1)|もぎ|300 愛してる(2)|もぎ|700 愛してる(3)|もぎ|1100

該当のソースコード

Python

1import pandas as pd 2import csv,json 3 4df = pd.read_csv("xxx.csv", encoding="shift-jis") 5df = df.groupby("作品名", as_index=None).sum() 6print(df)

試したこと

上記ソースコードでエラーに記載したような部分まではできるのですが、(1)、(2)と(3)をまとめるスキルがありませんのでご教授ください。

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

MAC OS High Sierra
ver.10.13.6
Python 3.4.3
ここにより詳細な情報を記載してください。

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

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

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

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

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

hayataka2049

2019/05/23 14:10

巻数のフォーマットは定まっていますか? そのフォーマットだけならやりようはあると思いますけど、「愛してる1」とか「愛してる 一」とか「愛してる壱」とか出てきたときに収拾がつかなくなる可能性が高いです。
kumer1

2019/05/23 14:11

はい。前提としてフォーマットは(1)・・・で続いていく形になります。
guest

回答4

0

ベストアンサー

素直に"作品名"と"巻数"を分離したDataFrameに変換しておくと良いかと思います。

Python

1import pandas as pd 2import io 3 4s = '''作品名|著者|売上 5愛してる(1)|もぎ|100 6愛してる(1)|もぎ|200 7愛してる(2)|もぎ|300 8愛してる(2)|もぎ|400 9愛してる(3)|もぎ|500 10愛してる(3)|もぎ|600''' 11df = pd.read_csv(io.StringIO(s), encoding="utf-8", sep='\|||') 12 13df = df["作品名"].str.extract('(\D*)((\d+))', expand=False).rename(columns={0:'作品名',1:'巻数'}).join(df.drop('作品名', axis=1)) 14# 作品名 巻数 著者 売上 15#0 愛してる 1 もぎ 100 16#1 愛してる 1 もぎ 200 17#2 愛してる 2 もぎ 300 18#3 愛してる 2 もぎ 400 19#4 愛してる 3 もぎ 500 20#5 愛してる 3 もぎ 600 21 22ret = df.groupby(['作品名','著者']).agg({'売上':'sum'}).reset_index() 23# 作品名 著者 売上 24#0 愛してる もぎ 2100

投稿2019/05/24 00:26

magichan

総合スコア15898

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

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

kumer1

2019/05/24 14:56

ありがとうございます。sepの部分が|||でエラーが出てしまいます。また'(\D*)((\d+))'の正規表現の意味を知りたいです。
magichan

2019/05/25 01:09

まず正規表現ですが、"\D*"は数字以外(0文字以上)、”\d+”は数字(1文字以上)に対応し、"(" および ")" はそのまま括弧に対応しておりますので'\D*(\d+)' にて元の作品名にマッチします。 で、今回はそのうちの タイトル部 "\D*" と巻数 "\d+" の部分を列として抜き出したいわけですので、その部分をさらに括弧 "()" で囲うことでグループ化しております。で結果 "(\D*)((\d+))" となります。
magichan

2019/05/25 01:20

今回のCSVファイルの区切り文字ですが、質問のサンプルでは何故か全角の "|" と半角の "|" が混在しております。これが混在していないのであれば単に sep="|" や sep="|" などで動作するのですが、区切り文字が2つあるので正規表現の or('|') を使って "\|" or('|') "|" としているわけです。 私の環境では上記で動作しているのですが、もし動作しないのであれば、engine='python' パラメータを指定してみてください。(できるのであれば、区切り文字を1種類に統一する方が良いかとおもいますが。)
guest

0

これで

python

1import pandas as pd 2import csv,json 3 4df = pd.read_csv("xxx.csv", encoding="shift-jis") 5df = df.replace('(\d+)','', regex=True) 6df = df.groupby("作品名", as_index=None).sum() 7print(df)

投稿2019/05/23 14:41

waku_nagoya

総合スコア200

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

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

0

もう少しスマートな方法もあるかもしれませんが、とりあえずこれで。

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.groupby.html

python

1import io 2import pandas as pd 3 4txt = """ 5作品名,著者,売上 6愛してる(1),もぎ,100 7愛してる(1),もぎ,200 8愛してる(2),もぎ,300 9愛してる(2),もぎ,400 10愛してる(3),もぎ,500 11愛してる(3),もぎ,600 12""" 13 14df = pd.read_csv(io.StringIO(txt), sep=",") 15df = df.groupby(df["作品名"].str.replace(r"(\d+)", ""), as_index=None).sum() 16print(df) 17""" => 18 売上 190 2100 20"""

投稿2019/05/23 14:32

編集2019/05/23 14:34
hayataka2049

総合スコア30933

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

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

hayataka2049

2019/05/23 14:42

ただ売上以外の列が消えると困るなぁ、どうやって直そ
guest

0

アラビア数字になっていればなんとかしてくれる方法は誰かが教えてくれそうなので、
アラビア数字に変換する方法が記されているリンクを提示いたします。

https://qiita.com/dosec/items/c6aef40fae6977fd89ab


ちなみに数字部分だけが異なるのであれば、正規表現を使うとよいです。


python

1import pandas as pd 2import io 3 4s = '''作品名|著者|売上 5愛してる(1)|もぎ|100 6愛してる(1)|もぎ|200 7愛してる(2)|もぎ|300 8愛してる(2)|もぎ|400 9愛してる(3)|もぎ|500 10愛してる(3)|もぎ|600''' 11s = s.replace('|', ',') 12s = s.replace('|', ',') 13 14df = pd.read_csv(io.StringIO(s), encoding="utf-8") 15 16df = df.groupby(df["作品名"].str.extract('(\D*)(\d+)', expand=False), axis=0).sum() 17print(df)

投稿2019/05/23 14:30

編集2019/05/23 15:24
mkgrei

総合スコア8560

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

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

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問