以下の行に沿ってデータフレームがあります。
Type Set
1 A Z
2 B Z
3 B X
4 C Y
Set = 'Z'の場合は緑色、Set = 'Z'の場合は 'red'と設定されたデータフレームと同じ長さ(=レコード数/行数)のデータフレームに別の列を追加します。
これを行うための最良の方法は何ですか?
選択する選択肢が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
リスト内包表記は、条件付きで別の列を作成するもう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
この猫にスキンを適用するもう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']]
これを達成することができるもう一つの方法は
df['color'] = df.Set.map( lambda x: 'red' if x == 'Z' else 'green')
以下は、 ここ で時間を計ったアプローチよりも遅いですが、複数の列の内容に基づいて追加の列を計算することができ、追加の列に対して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
これは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