web-dev-qa-db-ja.com

Pandas複数のifステートメントでのLambda関数でのApplyの使用

私はこのようなデータフレームの人のサイズに応じて分類を推測しようとしています:

      Size
1     80000
2     8000000
3     8000000000
...

私はそれを次のように見せたいです:

      Size        Classification
1     80000       <1m
2     8000000     1-10m
3     8000000000  >1bi
...

理想的なプロセスは次のようなラムダ関数を適用することであることを理解しています:

df['Classification']=df['Size'].apply(lambda x: "<1m" if x<1000000 else "1-10m" if 1000000<x<10000000 else ...)

ラムダ関数の複数のifsに関するいくつかの投稿をチェックしました これはサンプルリンクです if状態。

だから私はこの「非常にエレガントな」ソリューションを試しました:

df['Classification']=df['Size'].apply(lambda x: "<1m" if x<1000000 else pass)
df['Classification']=df['Size'].apply(lambda x: "1-10m" if 1000000 < x < 10000000 else pass)
df['Classification']=df['Size'].apply(lambda x: "10-50m" if 10000000 < x < 50000000 else pass)
df['Classification']=df['Size'].apply(lambda x: "50-100m" if 50000000 < x < 100000000 else pass)
df['Classification']=df['Size'].apply(lambda x: "100-500m" if 100000000 < x < 500000000 else pass)
df['Classification']=df['Size'].apply(lambda x: "500m-1bi" if 500000000 < x < 1000000000 else pass)
df['Classification']=df['Size'].apply(lambda x: ">1bi" if 1000000000 < x else pass)

「パス」がラムダ関数にも適用されないように見える:

df['Classification']=df['Size'].apply(lambda x: "<1m" if x<1000000 else pass)
SyntaxError: invalid syntax

パンダのapplyメソッドのラムダ関数内の複数のifステートメントの正しいシンタックスに関する提案はありますか?複数行または単一行のソリューションが私にとってはうまくいきます。

4
abutremutante

以下は、その上に構築できる小さな例です。

基本的に、 lambda x: x..は、関数の短い1行です。実際に必要なのは、自分で簡単に再作成できる機能です。

import pandas as pd

# Recreate the dataframe
data = dict(Size=[80000,8000000,800000000])
df = pd.DataFrame(data)

# Create a function that returns desired values
# You only need to check upper bound as the next Elif-statement will catch the value
def func(x):
    if x < 1e6:
        return "<1m"
    Elif x < 1e7:
        return "1-10m"
    Elif x < 5e7:
        return "10-50m"
    else:
        return 'N/A'
    # Add Elif statements....

df['Classification'] = df['Size'].apply(func)

print(df)

戻り値:

        Size Classification
0      80000            <1m
1    8000000          1-10m
2  800000000            N/A
6
Anton vBR

pd.cut関数

bins = [0, 1000000, 10000000, 50000000, ...]
labels = ['<1m','1-10m','10-50m', ...]

df['Classification'] = pd.cut(df['Size'], bins=bins, labels=labels)
5
MaxU

Numpyのsearchsortedを使用する

labels = np.array(['<1m', '1-10m', '10-50m', '>50m'])
bins = np.array([1E6, 1E7, 5E7])

# Using assign is my preference as it produces a copy of df with new column
df.assign(Classification=labels[bins.searchsorted(df['Size'].values)])

既存のデータフレームに新しい列を作成したい場合

df['Classification'] = labels[bins.searchsorted(df['Size'].values)]

いくつかの説明

Docs:np.searchsorted から

順序を維持するために要素を挿入する必要があるインデックスを見つけます。

並べ替えられた配列aのインデックスを見つけます。vの対応する要素がインデックスの前に挿入された場合、aの順序は保持されます。

labels配列の長さはbinsの長さよりも1だけ長くなります。何かがbinsの最大値より大きい場合、searchsorted-1を返します。 labelsをスライスすると、最後のラベルが取得されます。

2
piRSquared