web-dev-qa-db-ja.com

シリーズ/データフレーム列のPandas条件付き作成

以下の行に沿ってデータフレームがあります。

    Type       Set
1    A          Z
2    B          Z           
3    B          X
4    C          Y

Set = 'Z'の場合は緑色、Set = 'Z'の場合は 'red'と設定されたデータフレームと同じ長さ(=レコード数/行数)のデータフレームに別の列を追加します。

これを行うための最良の方法は何ですか?

207
user7289

選択する選択肢が2つしかない場合:

df['color'] = np.where(df['Set']=='Z', 'green', 'red')

例えば、

import pandas as pd
import numpy as np

df = pd.DataFrame({'Type':list('ABBC'), 'Set':list('ZZXY')})
df['color'] = np.where(df['Set']=='Z', 'green', 'red')
print(df)

収量

  Set Type  color
0   Z    A  green
1   Z    B  green
2   X    B    red
3   Y    C    red

2つ以上の条件がある場合は np.selectを使用してください。たとえば、color

  • (df['Set'] == 'Z') & (df['Type'] == 'A')の場合はyellow
  • それ以外の場合はblue(df['Set'] == 'Z') & (df['Type'] == 'B')の場合
  • それ以外の場合はpurple(df['Type'] == 'B')の場合
  • それ以外の場合はblack

それから使う

df = pd.DataFrame({'Type':list('ABBC'), 'Set':list('ZZXY')})
conditions = [
    (df['Set'] == 'Z') & (df['Type'] == 'A'),
    (df['Set'] == 'Z') & (df['Type'] == 'B'),
    (df['Type'] == 'B')]
choices = ['yellow', 'blue', 'purple']
df['color'] = np.select(conditions, choices, default='black')
print(df)

どれが

  Set Type   color
0   Z    A  yellow
1   Z    B    blue
2   X    B  purple
3   Y    C   black
490
unutbu

リスト内包表記は、条件付きで別の列を作成するもう1つの方法です。あなたの例のように、列でオブジェクトのdtypeを扱う場合、リスト内包表記は通常他のほとんどのメソッドよりも優れています。

リスト内包の例:

df['color'] = ['red' if x == 'Z' else 'green' for x in df['Set']]

%timeitテスト:

import pandas as pd
import numpy as np

df = pd.DataFrame({'Type':list('ABBC'), 'Set':list('ZZXY')})
%timeit df['color'] = ['red' if x == 'Z' else 'green' for x in df['Set']]
%timeit df['color'] = np.where(df['Set']=='Z', 'green', 'red')
%timeit df['color'] = df.Set.map( lambda x: 'red' if x == 'Z' else 'green')

1000 loops, best of 3: 239 µs per loop
1000 loops, best of 3: 523 µs per loop
1000 loops, best of 3: 263 µs per loop
84
cheekybastard

この猫にスキンを適用するもう1つの方法は、辞書を使って新しい値をリスト内のキーにマッピングすることです。

def map_values(row, values_dict):
    return values_dict[row]

values_dict = {'A': 1, 'B': 2, 'C': 3, 'D': 4}

df = pd.DataFrame({'INDICATOR': ['A', 'B', 'C', 'D'], 'VALUE': [10, 9, 8, 7]})

df['NEW_VALUE'] = df['INDICATOR'].apply(map_values, args = (values_dict,))

それはどのようなものですか:

df
Out[2]: 
  INDICATOR  VALUE  NEW_VALUE
0         A     10          1
1         B      9          2
2         C      8          3
3         D      7          4

このアプローチは、作成する_ ifelse _typeステートメントが多数ある場合に非常に強力になります(つまり、置き換える固有の値が多数あります)。

そしてもちろん、あなたはいつもこれをすることができます:

df['NEW_VALUE'] = df['INDICATOR'].map(values_dict)

しかし私のマシンでは、そのアプローチは上からのapplyアプローチの3倍以上遅くなります。

dict.getを使ってこれを行うこともできます。

df['NEW_VALUE'] = [values_dict.get(v, None) for v in df['INDICATOR']]
18
blacksite

これを達成することができるもう一つの方法は

df['color'] = df.Set.map( lambda x: 'red' if x == 'Z' else 'green')
16
acharuva

以下は、 ここ で時間を計ったアプローチよりも遅いですが、複数の列の内容に基づいて追加の列を計算することができ、追加の列に対して2つ以上の値を計算できます。

"Set"列だけを使った簡単な例:

def set_color(row):
    if row["Set"] == "Z":
        return "red"
    else:
        return "green"

df = df.assign(color=df.apply(set_color, axis=1))

print(df)
  Set Type  color
0   Z    A    red
1   Z    B    red
2   X    B  green
3   Y    C  green

色数と列数を考慮した例

def set_color(row):
    if row["Set"] == "Z":
        return "red"
    Elif row["Type"] == "C":
        return "blue"
    else:
        return "green"

df = df.assign(color=df.apply(set_color, axis=1))

print(df)
  Set Type  color
0   Z    A    red
1   Z    B    red
2   X    B  green
3   Y    C   blue
11
bli

これはPandasの最新の更新で可能になったのかもしれませんが、これまでのところこの質問に対する最短の回答であり、おそらく最良の回答であると思います。必要に応じて、1つの条件または複数の条件を使用できます。

df=pd.DataFrame(dict(Type='A B B C'.split(), Set='Z Z X Y'.split()))
df['Color'] = "red"
df.loc[(df['Set']=="Z"), 'Color'] = "green"
print(df)

# result: 
  Type Set  Color
0    A   Z  green
1    B   Z  green
2    B   X    red
3    C   Y    red
1
HKRC