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

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

新規登録して質問してみよう
ただいま回答率
85.48%
GROUP BY

GROUP BYとはSQL文のひとつで、SELECT文において特定の列の値が等しい行ごとに表をグループ化します。

Python

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

pandas

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

Q&A

解決済

2回答

5018閲覧

groupbyした各groupから特定条件を満たす要素を1個づつ取り出したい

kani_miso

総合スコア6

GROUP BY

GROUP BYとはSQL文のひとつで、SELECT文において特定の列の値が等しい行ごとに表をグループ化します。

Python

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

pandas

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

0グッド

1クリップ

投稿2020/02/27 17:58

質問概要

groupbyした各groupから特定条件を満たす要素を1行づつ取り出す処理を実装したいです。
python初学者で基本的な質問かもしれませんが、お知恵を拝借できますでしょうか。

実現したいこと

以下のようなdataframeに対し、日時でgroupbyを行った各groupの中から以下の条件を満たす行を1行づつ抽出したいです。

■group内の抽出条件
・エラーフラグが立っていない(エラー≠1)
・エラーフラグが立っていないデータが複数ある場合、IDが A>B>C の優先度で抽出する
・すべてエラーフラグが立っている場合、何も抽出しない

具体的には以下の例です。

■元のdataframe

日時ID計測値エラー
2020-02-01 9:00:00A01
2020-02-01 9:00:00B100
2020-02-01 9:00:00C130
2020-02-01 10:00:00A200
2020-02-01 10:00:00B220
2020-02-01 10:00:00C180
2020-02-01 11:00:00A01
2020-02-01 11:00:00B01
2020-02-01 11:00:00C01
2020-02-01 12:00:00A01
2020-02-01 12:00:00B01
2020-02-01 12:00:00C130

■欲しいdataframe

日時ID計測値エラー
2020-02-01 9:00:00B100
2020-02-01 10:00:00A200
2020-02-01 12:00:00C130

よろしくお願いします。

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

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

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

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

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

guest

回答2

0

GroupBy.apply() から呼んだ関数内で質問に書かれた条件でフィルタリングするように記述するだけです。
今回の場合は

Python

1df[df['エラー']==0].groupby('日時').apply(lambda d:d.sort_values('ID').iloc[[0]])

でよいのではないでしょうか。

関数内で結果が空の場合の条件分岐をするのが面倒だったので、groupbyよりも先にエラー列でフィルタリングして、対象がない場合はそもそもグループが作成されないようにしてあります。

一応動作確認

Python

1import pandas as pd 2import io 3 4data = """ 5日時,ID,計測値,エラー 62020-02-01 9:00:00,A,0,1 72020-02-01 9:00:00,B,10,0 82020-02-01 9:00:00,C,13,0 92020-02-01 10:00:00,A,20,0 102020-02-01 10:00:00,B,22,0 112020-02-01 10:00:00,C,18,0 122020-02-01 11:00:00,A,0,1 132020-02-01 11:00:00,B,0,1 142020-02-01 11:00:00,C,0,1 152020-02-01 12:00:00,A,0,1 162020-02-01 12:00:00,B,0,1 172020-02-01 12:00:00,C,13,0 18""" 19 20df = pd.read_csv(io.StringIO(data), parse_dates=['日時']) 21 22 23ret = df[df['エラー']==0].groupby('日時', group_keys=False).apply(lambda d:d.sort_values('ID').iloc[[0]]) 24print(ret) 25# 日時 ID 計測値 エラー 26#1 2020-02-01 09:00:00 B 10 0 27#3 2020-02-01 10:00:00 A 20 0 28#11 2020-02-01 12:00:00 C 13 0

投稿2020/02/28 00:31

magichan

総合スコア15898

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

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

kani_miso

2020/02/28 09:28

ありがとうございます。 回答いただいた方法でできました! 回答いただいたお二方のやりかたどちらも参考になるものでとても助かりました。 申し訳ありませんがベストアンサーは先に回答いただいた方にさせていただきました。
guest

0

ベストアンサー

元のdataframeが df という変数に入っているとして、以下の処理で実現できるかと思いました。
下記の通り、カラム名について、エラーをERROR、日時をdate_timeという名前にしています。

元のdataframe

date_timeIDVALUEERROR
2020/02/01 9:00:00A01
2020/02/01 9:00:00B100
2020/02/01 9:00:00C130
2020/02/01 10:00:00A200
2020/02/01 10:00:00B220
2020/02/01 10:00:00C180
2020/02/01 11:00:00A01
2020/02/01 11:00:00B01
2020/02/01 11:00:00C01
2020/02/01 12:00:00A01
2020/02/01 12:00:00B01
2020/02/01 12:00:00C130

処理内容

python

1# date_timeを型変換 2df['date_time'] = pd.to_datetime(df['date_time']) 3 4# エラーが1のものだけ抽出 5df = df.query("ERROR != 1") 6 7# ABCをアスキーコード(数字)に変換 8df["ID_num"] = df["ID"].apply(lambda x: ord(x)) 9 10# datetimeでgroup_by 11df_group = df.groupby(by="date_time") 12 13# 各groupにおいて、ID_numが最小の行のrowを取得する 14df = df.loc[df_group['ID_num'].idxmin(),:] 15 16# 最後に、date_timeでソート 17df = df.sort_values('date_time', ascending=True)

得られる結果

上記を実行することで下記のような結果を得ることができるはずです
イメージ説明

参考になる記事

アスキーコードについて
idxminの使い方

投稿2020/02/27 20:12

編集2020/02/27 20:24
ash_fk

総合スコア45

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

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

kani_miso

2020/02/28 09:25

ありがとうございます。 無事やりたいことが実現できました! 助かりました。
ash_fk

2020/02/28 12:43

解決したようで、良かったです!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問