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

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

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

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

Python

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

pandas

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

Q&A

解決済

3回答

983閲覧

pandasのdataframeでA列が特定の条件に当てはまる場合にB列の値が上位n個までC列に特定の値を入れたい

pariparigorilla

総合スコア14

Python 3.x

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

Python

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

pandas

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

0グッド

0クリップ

投稿2020/09/15 10:43

表題の通り、pythonでpandasを使っていますが、dataframeの処理で実現したいことができない状態です。


A列が、A1,A2,A3...というカテゴリ変数
B1列/B2列が、全データをある基準に基づいてランク付けされた順位(1,2,...,全データ数)
C列が、空欄
とします。

やりたい処理は、A列がA1のデータのB1の上位n位までのデータのC列に1を入れ、A列がA2のデータのB2の上位n位までのデータのc列に1を入れるという処理です。

df.loc[(df[B1] <= n) & (df[A] == A1), C] = 1
df.loc[(df[B2] <= n) & (df[A] == A2), C] = 1

現在、このような処理を書いているのですが、これだとB1とB2の順位がどちらもn以下の場合重複して選ばれてしまいます。
やりたい処理としては重複してほしくなく、1行目の処理はA1のデータだけでB1のランキング上位n個、2行目はA2のデータだけでB2のランキング上位n個のものを選定(=c列に1を代入)したいです。

いい方法が思いつかず、どうしたら実現できますでしょうか?

pythonのバージョンは3.7.7です

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

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

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

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

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

meg_

2020/09/15 11:08

具体的にdataframeを提示してください。
pariparigorilla

2020/09/15 14:20 編集

こんなイメージですね。 n=3のときの例です。 index| A | B1 | B2 | C 0 |A1 | 19 | 5 | 1 |A2 | 12 | 19 | 2 |A3 | 10 | 9 | 3 |A1 | 14 | 13 | 4 |A2 | 8 | 1 | 1(B2が1で、A2の中で1番) 5 |A1 | 11 | 16 | 6 |A2 | 18 | 10 | 7 |A2 | 9 | 4 | 1(B2が4で、A2の中で2番) 8 |A1 | 5 | 14 | 1(B1が5で、A1の中で3番) 9 |A3 | 20 | 7 | 10 |A1 | 13 | 2 | 11 |A1 | 4 | 18 | 1(B1が4で、A1の中で2番) 12 |A2 | 7 | 11 | 13 |A2 | 1 | 8 | 1(B2が8で、A2の中で3番) 14 |A3 | 15 | 3 | 15 |A3 | 6 | 17 | 16 |A2 | 17 | 15 | 17 |A1 | 2 | 12 | 1(B1が2で、A1の中で1番) 18 |A1 | 16 | 6 | 19 |A2 | 3 | 20 |
meg_

2020/09/15 13:21

情報は質問に追記してください。回答が付きやすくなるかと思います。
guest

回答3

0

ベストアンサー

df.nsmallest(n, '列名')メソッドを用いると、df['列名']の上位n位を選択することができます。
pandas.DataFrame.nsmallest — pandas documentation

なので、A列がA1やA2に一致するデータフレームに対してこのメソッドを用いれば希望のインデックス(行番号)を取得することができます。

python

1import io 2import pandas as pd 3 4txt = """index,A,B1,B2,C 50,A1,19,5, 61,A2,12,19, 72,A3,10,9, 83,A1,14,13, 94,A2,8,1, 105,A1,11,16, 116,A2,18,10, 127,A2,9,4, 138,A1,5,14, 149,A3,20,7, 1510,A1,13,2, 1611,A1,4,18, 1712,A2,7,11, 1813,A2,1,8, 1914,A3,15,3, 2015,A3,6,17, 2116,A2,17,15, 2217,A1,2,12, 2318,A1,16,6, 2419,A2,3,20,""" 25df = pd.read_csv(io.StringIO(txt), index_col='index')

このとき、

python

1n = 3 2df.loc[df[df['A'] == 'A1'].nsmallest(n, 'B1').index, 'C'] = 1 3df.loc[df[df['A'] == 'A2'].nsmallest(n, 'B2').index, 'C'] = 1 4 5df 6# A B1 B2 C 7# index 8# 0 A1 19 5 NaN 9# 1 A2 12 19 NaN 10# 2 A3 10 9 NaN 11# 3 A1 14 13 NaN 12# 4 A2 8 1 1.0 13# 5 A1 11 16 NaN 14# 6 A2 18 10 NaN 15# 7 A2 9 4 1.0 16# 8 A1 5 14 1.0 17# 9 A3 20 7 NaN 18# 10 A1 13 2 NaN 19# 11 A1 4 18 1.0 20# 12 A2 7 11 NaN 21# 13 A2 1 8 1.0 22# 14 A3 15 3 NaN 23# 15 A3 6 17 NaN 24# 16 A2 17 15 NaN 25# 17 A1 2 12 1.0 26# 18 A1 16 6 NaN 27# 19 A2 3 20 NaN

投稿2020/09/16 01:04

kirara0048

総合スコア1399

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

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

pariparigorilla

2020/09/16 07:36

回答ありがとうございます!所望の挙動になりました。
guest

0

こんな感じのコードで、目的の動作をすると思います。

Python

1# A列でグループ分けをしつつ各グループ内のB1/B2列の順位を求める 2categorized_rank_b1 = df.groupby('A')['B1'].rank().astype(int) 3categorized_rank_b2 = df.groupby('A')['B2'].rank().astype(int) 4# A列がA1ならB1列順位、 A列がA2ならB2列順位、どちらかがn以下であれば、TrueをC列に入れる 5df['C'] = (df['A'] == 'A1') & (categorized_rank_b1 <= n) | (df['A'] == 'A2') & (categorized_rank_b2 <= n) 6# C列のTrue/Falseを、1/0に変換する 7df['C'] = df['C'].astype(int)

投稿2020/09/15 13:46

toast-uz

総合スコア3266

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

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

pariparigorilla

2020/09/16 07:35

回答ありがとうございます!所望の挙動になりました。
guest

0

update()rank()を使って、以下のように書けます。

python

1n = 3 2 3df['C'] = False 4df['C'].update(df.loc[df['A'] == 'A1', 'B1'].rank() <= n) 5df['C'].update(df.loc[df['A'] == 'A2', 'B2'].rank() <= n) 6df['C'] = df['C'].astype(int)

update()はもとのindexにあわせて更新してくれるので、一部切り出して計算した結果をもとのデータフレームに代入したいときに、役に立ちます。

投稿2020/09/16 01:53

bsdfan

総合スコア4794

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問