Creación condicional de pandas de una serie / columna de dataframe.

Tengo un dataframe a lo largo de las líneas de abajo:

Type Set 1 AZ 2 BZ 3 BX 4 CY 

Quiero agregar otra columna al dataframe (o generar una serie) de la misma longitud que el dataframe (= igual número de registros / filas) que establece un color verde si Set = ‘Z’ y ‘rojo’ si Set = de lo contrario .

¿Cuál es la mejor manera de hacer esto?

Si solo tiene dos opciones para elegir:

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

Por ejemplo,

 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) 

rendimientos

  Set Type color 0 ZA green 1 ZB green 2 XB red 3 YC red 

Si tiene más de dos condiciones, use np.select . Por ejemplo, si quieres que el color sea

  • yellow cuando (df['Set'] == 'Z') & (df['Type'] == 'A')
  • de lo contrario, blue cuando (df['Set'] == 'Z') & (df['Type'] == 'B')
  • de lo contrario purple cuando (df['Type'] == 'B')
  • de lo contrario black

entonces usa

 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) 

cuyos rendimientos

  Set Type color 0 ZA yellow 1 ZB blue 2 XB purple 3 YC black 

La comprensión de la lista es otra forma de crear otra columna condicionalmente. Si está trabajando con tipos de objetos en columnas, como en su ejemplo, las comprensiones de listas generalmente superan a la mayoría de los otros métodos.

Ejemplo de comprensión de lista:

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

% de pruebas de tiempo:

 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 

Aquí hay otra forma de proteger a este gato, usando un diccionario para asignar nuevos valores a las claves en la lista:

 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,)) 

¿Cómo se ve?

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

Este enfoque puede ser muy poderoso cuando tiene que hacer muchas declaraciones tipo ifelse (es decir, muchos valores únicos para reemplazar).

Y por supuesto siempre puedes hacer esto:

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

Pero ese enfoque es más de tres veces más lento que el enfoque apply desde arriba, en mi máquina.

Y también puedes hacer esto, usando dict.get :

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

Otra forma en que esto podría lograrse es

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

Lo siguiente es más lento que los enfoques cronometrados aquí , pero podemos calcular la columna adicional en función del contenido de más de una columna, y se pueden calcular más de dos valores para la columna adicional.

Ejemplo simple usando solo la columna “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 ZA red 1 ZB red 2 XB green 3 YC green 

Ejemplo con más colores y más columnas tomadas en cuenta:

 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 ZA red 1 ZB red 2 XB green 3 YC blue 

Tal vez esto haya sido posible con las actualizaciones más recientes de Pandas, pero creo que la siguiente es la respuesta más corta y quizás la mejor, hasta ahora. Puede utilizar una condición o varias dependiendo de su necesidad.

 df=pd.DataFrame(dict(Type='ABB C'.split(), Set='ZZX Y'.split())) df['Color'] = "red" df.loc[(df['Set']=="Z"), 'Color'] = "green" print(df) # result: Type Set Color 0 AZ green 1 BZ green 2 BX red 3 CY red