Chcę zastosować moją funkcję niestandardową (używa się if-else drabinę) do tych sześciu kolumn ( ERI_Hispanic
, ERI_AmerInd_AKNatv
, ERI_Asian
, ERI_Black_Afr.Amer
, ERI_HI_PacIsl
,ERI_White
) w każdym rzędzie moim dataframe.
Próbowałem różnych metod z innych pytań, ale nadal nie mogę znaleźć właściwej odpowiedzi na mój problem. Najważniejsze jest to, że jeśli dana osoba jest latynoska, nie można jej liczyć jako niczego innego. Nawet jeśli mają „1” w innej kolumnie etnicznej, nadal są liczone jako Hiszpanie, a nie dwie lub więcej ras. Podobnie, jeśli suma wszystkich kolumn ERI jest większa niż 1, są one liczone jako dwie lub więcej ras i nie mogą być liczone jako unikalna pochodzenie etniczne (z wyjątkiem Latynosów). Mam nadzieję, że ma to sens. Każda pomoc będzie mile widziana.
To prawie jak wykonywanie pętli for przez każdy wiersz i jeśli każdy rekord spełnia kryterium, są one dodawane do jednej listy i usuwane z oryginału.
Na podstawie poniższej ramki danych muszę obliczyć nową kolumnę na podstawie następującej specyfikacji SQL:
========================= KRYTERIA ======================== =======
IF [ERI_Hispanic] = 1 THEN RETURN “Hispanic”
ELSE IF SUM([ERI_AmerInd_AKNatv] + [ERI_Asian] + [ERI_Black_Afr.Amer] + [ERI_HI_PacIsl] + [ERI_White]) > 1 THEN RETURN “Two or More”
ELSE IF [ERI_AmerInd_AKNatv] = 1 THEN RETURN “A/I AK Native”
ELSE IF [ERI_Asian] = 1 THEN RETURN “Asian”
ELSE IF [ERI_Black_Afr.Amer] = 1 THEN RETURN “Black/AA”
ELSE IF [ERI_HI_PacIsl] = 1 THEN RETURN “Haw/Pac Isl.”
ELSE IF [ERI_White] = 1 THEN RETURN “White”
Komentarz: Jeśli flaga ERI dla języka hiszpańskiego jest prawdziwa (1), pracownik jest klasyfikowany jako „hiszpański”
Komentarz: Jeśli więcej niż 1 nie-hiszpańska flaga ERI jest prawdziwa, zwróć „dwa lub więcej”
====================== DATAFRAME ===========================
lname fname rno_cd eri_afr_amer eri_asian eri_hawaiian eri_hispanic eri_nat_amer eri_white rno_defined
0 MOST JEFF E 0 0 0 0 0 1 White
1 CRUISE TOM E 0 0 0 1 0 0 White
2 DEPP JOHNNY 0 0 0 0 0 1 Unknown
3 DICAP LEO 0 0 0 0 0 1 Unknown
4 BRANDO MARLON E 0 0 0 0 0 0 White
5 HANKS TOM 0 0 0 0 0 1 Unknown
6 DENIRO ROBERT E 0 1 0 0 0 1 White
7 PACINO AL E 0 0 0 0 0 1 White
8 WILLIAMS ROBIN E 0 0 1 0 0 0 White
9 EASTWOOD CLINT E 0 0 0 0 0 1 White
Odpowiedzi:
OK, dwa kroki do tego - najpierw jest napisanie funkcji wykonującej tłumaczenie, które chcesz - podałem przykład na podstawie twojego pseudokodu:
Być może warto to omówić, ale wydaje się, że to załatwia sprawę - zauważ, że parametr wchodzący w funkcję jest uważany za obiekt serii oznaczony jako „wiersz”.
Następnie użyj funkcji Apply w pandach, aby zastosować funkcję - np
Zwróć uwagę na specyfikator oś = 1, co oznacza, że aplikacja jest wykonywana w wierszu, a nie na poziomie kolumny. Wyniki są tutaj:
Jeśli jesteś zadowolony z tych wyników, uruchom go ponownie, zapisując wyniki w nowej kolumnie w oryginalnej ramce danych.
Powstała ramka danych wygląda następująco (przewiń w prawo, aby zobaczyć nową kolumnę):
źródło
df.apply(label_race, axis=1)
return 'Other'
linię, nareturn row['rno_defined']
którą powinna zastąp wartość z tej kolumny w tych przypadkach, w których zestaw instrukcji if / then nie znajduje dopasowania (tj. gdzie obecnie widzisz „Inne”).df.apply(lambda row: label_race (row),axis=1)
dodf.apply(label_race, axis=1)
Ponieważ jest to pierwszy wynik Google dla „nowej kolumny pandy od innych”, oto prosty przykład:
Jeśli go dostaniesz
SettingWithCopyWarning
, możesz to zrobić również w ten sposób:Źródło: https://stackoverflow.com/a/12555510/243392
A jeśli nazwa kolumny zawiera spacje, możesz użyć następującej składni:
A oto dokumentacja do zastosowania i przypisania .
źródło
SettingWithCopyWarning
kiedy to robię.df['c'] = df.apply(lambda row: row.a + row.b, axis=1)
Czy to jest prawdziwy problem, czy nie powinienem się tym martwić?Powyższe odpowiedzi są całkowicie poprawne, ale istnieje wektoryzowane rozwiązanie w postaci
numpy.select
. Umożliwia to definiowanie warunków, a następnie definiowanie wyników dla tych warunków, znacznie wydajniej niż przy użyciuapply
:Najpierw zdefiniuj warunki:
Teraz zdefiniuj odpowiednie dane wyjściowe:
Wreszcie, używając
numpy.select
:Dlaczego warto z
numpy.select
niego korzystaćapply
? Oto kilka kontroli wydajności:Używanie
numpy.select
zapewnia nam znacznie lepszą wydajność, a rozbieżność będzie się zwiększać w miarę wzrostu danych.źródło
.apply()
przyjmuje funkcję jako pierwszy parametr; przekażlabel_race
funkcję w następujący sposób:Nie trzeba tworzyć funkcji lambda, aby przekazać funkcję.
źródło
Spróbuj tego,
O / P:
użyj
.loc
zamiastapply
.poprawia wektoryzację.
.loc
działa w prosty sposób, zamaskuj wiersze w oparciu o warunek, zastosuj wartości do zamrożonych wierszy.więcej informacji na stronie, .loc docs
Wskaźniki wydajności:
Zaakceptowana odpowiedź:
Moja proponowana odpowiedź:
źródło