Pandy warunkowe utworzenie kolumny serii / ramki danych

Mam ramkę danych zgodnie z poniższymi wersjami:

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

Chcę dodać kolejną kolumnę do ramki danych (lub wygenerować serię) o tej samej długości co ramka danych (równa liczba rekordów/wierszy), która ustawi kolor 'green' if Set == 'Z' i 'red' if Set równa się cokolwiek innego.

Jaki jest najlepszy sposób, aby to zrobić?

Author: daaawx, 2013-11-11

9 answers

Jeśli masz tylko dwie opcje do wyboru:

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

Na przykład,

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

Jeśli masz więcej niż dwa warunki, użyj np.select. Na przykład, jeśli chcesz color BYĆ

  • yellow kiedy (df['Set'] == 'Z') & (df['Type'] == 'A')
  • inaczej blue Kiedy (df['Set'] == 'Z') & (df['Type'] == 'B')
  • inaczej purple Kiedy (df['Type'] == 'B')
  • inaczej black,

Następnie użyj

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)

Co daje

  Set Type   color
0   Z    A  yellow
1   Z    B    blue
2   X    B  purple
3   Y    C   black
 822
Author: unutbu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-09 21:47:51

Rozumienie listy jest innym sposobem warunkowego tworzenia kolejnej kolumny. Jeśli pracujesz z obiektowymi typami dtypów w kolumnach, tak jak w przykładzie, składanie list zazwyczaj przewyższa większość innych metod.

Przykładowa lista:

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

%testy czasu:

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
 134
Author: cheekybastard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-16 16:49:28

Innym sposobem, w jaki można to osiągnąć jest

df['color'] = df.Set.map( lambda x: 'red' if x == 'Z' else 'green')
 25
Author: acharuva,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-06 04:43:52

Oto kolejny sposób na skórkę tego kota, używając słownika do mapowania nowych wartości na kluczach na liście:

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

Jak to wygląda:

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

To podejście może być bardzo skuteczne, gdy masz wiele instrukcji typu ifelse do złożenia (tj. wiele unikalnych wartości do zastąpienia).

I oczywiście zawsze możesz to zrobić:

df['NEW_VALUE'] = df['INDICATOR'].map(values_dict)
Ale to podejście jest ponad trzy razy wolniejsze niż podejście z góry, na mojej maszynie.

I ty też możesz to zrobić, użycie dict.get:

df['NEW_VALUE'] = [values_dict.get(v, None) for v in df['INDICATOR']]
 23
Author: blacksite,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-16 20:59:07

Poniższy tekst jest wolniejszy niż podejście timed tutaj, ale możemy obliczyć dodatkową kolumnę na podstawie zawartości więcej niż jednej kolumny, a więcej niż dwie wartości mogą być obliczone dla dodatkowej kolumny.

Prosty przykład z użyciem kolumny "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

Przykład z większą liczbą kolorów i większą liczbą kolumn:

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
W 2009 roku firma została założona przez prof.]}

Możliwe jest również użycie plydata do tego typu rzeczy (wydaje się to nawet wolniejsze niż użycie assign i apply).

from plydata import define, if_else

Proste if_else:

df = define(df, color=if_else('Set=="Z"', '"red"', '"green"'))

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

Zagnieżdżone if_else:

df = define(df, color=if_else(
    'Set=="Z"',
    '"red"',
    if_else('Type=="C"', '"green"', '"blue"')))

print(df)                            
  Set Type  color
0   Z    A    red
1   Z    B    red
2   X    B   blue
3   Y    C  green
 21
Author: bli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-06-21 15:23:50

Możesz po prostu użyć potężnej metody .loc i użyć jednego warunku lub kilku w zależności od potrzeb (testowane z pandas=1.0.5).

Podsumowanie Kodu:

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"

#practice!
df.loc[(df['Set']=="Z")&(df['Type']=="B")|(df['Type']=="C"), 'Color'] = "purple"

Wyjaśnienie:

df=pd.DataFrame(dict(Type='A B B C'.split(), Set='Z Z X Y'.split()))

# df so far: 
  Type Set  
0    A   Z 
1    B   Z 
2    B   X 
3    C   Y

Dodaj kolumnę "kolor" i ustaw wszystkie wartości na "czerwony"

df['Color'] = "red"

Zastosuj jeden warunek:

df.loc[(df['Set']=="Z"), 'Color'] = "green"


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

Lub wiele warunków, jeśli chcesz:

df.loc[(df['Set']=="Z")&(df['Type']=="B")|(df['Type']=="C"), 'Color'] = "purple"

Możesz przeczytać o operatorach logicznych i warunkowym wyborze pand tutaj: operatory logiczne do indeksowania boolowskiego w Pandy

 14
Author: Hossein,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2021-01-31 07:17:13

Jedna wkładka z metodą .apply() jest następująca:

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

Po tym, df ramka danych wygląda tak:

>>> print(df)
  Type Set  color
0    A   Z  green
1    B   Z  green
2    B   X    red
3    C   Y    red
 1
Author: Jaroslav Bezděk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-10-10 14:30:03

Jeśli pracujesz z massive data, najlepiej byłoby zastosować podejście memoized:

# First create a dictionary of manually stored values
color_dict = {'Z':'red'}

# Second, build a dictionary of "other" values
color_dict_other = {x:'green' for x in df['Set'].unique() if x not in color_dict.keys()}

# Next, merge the two
color_dict.update(color_dict_other)

# Finally, map it to your column
df['color'] = df['Set'].map(color_dict)

takie podejście będzie najszybsze, gdy masz wiele powtarzających się wartości. moją ogólną zasadą jest zapamiętanie, kiedy: data_size > 10**4 & n_distinct data_size/4

E. X. Memoize w przypadku 10,000 wierszy z 2,500 lub mniej odrębnych wartości.

 0
Author: Yaakov Bressler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-12-08 18:42:01

Możesz używać metod pandy where Oraz mask:

df['color'] = 'green'
df['color'] = df['color'].where(df['Set']=='Z', other='red')
# Replace values where the condition is False

Lub

df['color'] = 'red'
df['color'] = df['color'].mask(df['Set']=='Z', other='green')
# Replace values where the condition is True

Wyjście:

  Type Set  color
1    A   Z  green
2    B   Z  green
3    B   X    red
4    C   Y    red
 0
Author: Mykola Zotko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2021-02-02 07:55:39