Mam te kolumny w ramce danych Pythona o nazwie admission:

Patient ID, Regular ward, Semi-intensive, Intensive
1                0               0            0
2                1               0            0
3                0               1            0
4                0               1            0
5                0               0            1

Wykonałem już następującą transformację:

 Patient ID, Admission type
 1                 0
 2                 1
 3                 2
 4                 2
 5                 3

Zasadniczo, aby osiągnąć tę transformację, tworzę nową kolumnę o nazwie `` Brak wstępu '' zawierającą 1, jeśli trzy kolumny (Zwykły oddział, Średnio intensywny, Intensywny) są równe 0, w przeciwnym razie zwraca 0.

Następnie zamapowałem wartości w każdej kolumnie na jedną kolumnę, aby zwrócić nazwę kolumny, zamiast 0 lub 1.

Patient ID, Admission type
 1          No admission
 2          Regular ward
 3          Semi-intensive
 4          Semi-intensive
 5          Intensive

I ponownie wykonaj mapowanie dla Bez wstępu = 0, Oddział regularny = 1, Średnio-intensywny = 2, Intensywny = 3

Oto moja pełna transformacja kodu.

df['No admission'] = None
admission= df.iloc[:,3:6] # Selecting only the three columns mentioned above.

for row in df.index:
    if admission.apply(any,axis=1).values[row]:
        df.loc[row,'No admission'] = 0
    else:
        df.loc[row,'No admission'] = 1

cols = [4,5,6,106]
df.insert(loc = 1,
          column = 'Admission type',
          value = df.iloc[:,cols].apply(np.argmax, axis=1))

df.drop(df.columns[cols],axis=1,inplace=True)

le = LabelEncoder()
le.fit(df['Admission type'])
df['Admission type'] = le.transform(df['Admission type'])

Chodzi o to, że mój oryginalny zbiór danych ma 5644 wierszy i 111 kolumn. Czas wykonania na wyjaśnienie tego, o czym wspomniałem powyżej, to około 10 minut!

Wiem, że to lepszy sposób, aby to poprawić i doceniam każdą pomoc.

0
Henrique Branco 1 kwiecień 2020, 04:47

4 odpowiedzi

Najlepsza odpowiedź

Jak używanie np.where() poprawia wydajność? Wyobrażam sobie, że byłoby to znacznie szybsze.

Wejście:

Patient ID  Regular ward   Semi-intensive  Intensive
1                0               0            0
2                1               0            0
3                0               1            0
4                0               1            0
5                0               0            1

Kod:

df=pd.read_clipboard(sep='\\s\\s+'))
df['Admission type'] = ''
df['Admission type'] = np.where(df['Regular ward'] == 1, 'Regular ward', df['Admission type'])
df['Admission type'] = np.where(df['Semi-intensive'] == 1, 'Semi-intensive', df['Admission type'])
df['Admission type'] = np.where(df['Intensive'] == 1, 'Intensive', df['Admission type'])
df['Admission type'] = np.where((df['Regular ward'] + df['Semi-intensive'] + df['Intensive'] == 0),
                              'No admission', df['Admission type'])
df=df[['Patient ID', 'Admission type']]
df 

Wynik:

    Patient ID   Admission type
0   1          No admission
1   2          Regular ward
2   3          Semi-intensive
3   4          Semi-intensive
4   5          Intensive
1
David Erickson 1 kwiecień 2020, 05:01
admission_copy = admission.copy()
admission_copy["Semi-intensive"] = admission_copy["Semi-intensive"]*2
admission_copy["Intensive"] = admission_copy["Intensive"]*3
df["Admission type"] = admission_copy.sum(axis=1)

Zakłada się, że nie ma pacjentów z dwoma typami przyjęć. Jeśli potrzebujesz tylko zwykłych, pół i intensywnych kolumn do utworzenia tej kolumny, nie musisz kopiować df, możesz po prostu zmienić df bezpośrednio.

Edycja: Ponadto założyłem, że kolumna indeksu to „pacjent”. Jeśli jest to jego własna kolumna, po prostu nie włączaj jej jako części swojego wycinka df „wstępu” i powinna nadal działać

2
Ryohei Namiki 1 kwiecień 2020, 02:21

Możesz użyć dot, aby scalić nazwy kolumn w każdą 1 i utworzyć z nich nową ramkę danych.

df1 = df[['Regular-ward', 'Semi-intensive', 'Intensive']]
df_final = df[['Patient_ID']].assign(**{'Admission Type': df1.dot(df1.columns).replace('', 'No admission')})

Out[16]:
   Patient_ID  Admission Type
0           1   No admission
1           2    Regular-ward
2           3  Semi-intensive
3           4  Semi-intensive
4           5       Intensive
0
Andy L. 1 kwiecień 2020, 02:10

Pomysł polega na utworzeniu indeksu według pierwszej kolumny, więc możliwe jest użycie mnożenia macierzy przez wszystkie kolumny przez DataFrame.dot i zamień puste ciągi na No admission, ostatnia konwersja indeksu na kolumnę:

df = df.set_index('Patient ID')
df = df.dot(df.columns).replace('','No admission').reset_index(name='Admission type')
print (df)
   Patient ID  Admission type
0           1    No admission
1           2    Regular ward
2           3  Semi-intensive
3           4  Semi-intensive
4           5       Intensive

Podobny pomysł z filtrem wszystkich kolumn bez wcześniejszego:

s = df.iloc[:, 1:].dot(df.columns[1:]).replace('','No admission').rename('Admission type')
df = df.iloc[:, [0]].join(s)

Jeśli to możliwe, rozwiązanie wielu 1 na wiersze jest zmieniane przez dodanie separatora do nazw kolumn i Series.str.rstrip:

print (df)
   Patient ID  Regular ward  Semi-intensive  Intensive
0           1             0               0          0
1           2             1               0          1
2           3             0               1          0
3           4             0               1          0
4           5             0               0          1


df = df.set_index('Patient ID')
df = (df.dot(df.columns + ',')
        .str.rstrip(',')
        .replace('','No admission')
        .reset_index(name='Admission type'))
print (df)
   Patient ID          Admission type
0           1            No admission
1           2  Regular ward,Intensive
2           3          Semi-intensive
3           4          Semi-intensive
4           5               Intensive
0
jezrael 1 kwiecień 2020, 05:13