2015-04-21 16 views
12

pracuję z Pand i mam ramkę danych, gdzie możemy mieć jedną z trzech wartości zaludnionych:Kombajny wartości kolumny ramka danych Pandy w nowej kolumnie

ID_1 ID_2 ID_3 
abc  NaN  NaN 
NaN  def  NaN 
NaN  NaN  ghi 
NaN  NaN  jkl 
NaN  mno  NaN 
pqr  NaN  NaN 

A moim celem jest połączyć te trzy kolumny do nowych kolumn w mojej ramce danych:

ID_1 ID_2 ID_3 Combined_ID 
abc  NaN  NaN abc 
NaN  def  NaN def 
NaN  NaN  ghi ghi 
NaN  NaN  jkl jkl 
NaN  mno  NaN mno 
pqr  NaN  NaN pqr 

Idealnie byłoby to po prostu znaleźć cokolwiek istnieje nie zerowa wartość w kolumnach 1 do 3, ale mogę też złączyć ponieważ powinniśmy mieć tylko jedną z trzech zaludnionych dla każdego wiersza . Dzięki.

df_note = pd.read_csv("NoteIds.csv") 
df_note['Combined_ID'] = # ID_1 + ID_2 + ID_3 
+1

Czy jesteśmy pewni, że w jednym wierszu jest tylko jedna wartość inna niż NaN? – DSM

+0

@EdChum - Istnieją również inne kolumny. Tak, tak, tylko jeden non NaN, ale tylko dla tych 3 kolumn, a nie całego rzędu. – EMC

Odpowiedz

3

Załóżmy, że w jednym rzędzie może być więcej niż jedna wartość inna niż NaN. Nadal powinno to działać.

In [43]: df['Combined_ID'] = df.apply(
       lambda x : ''.join([e for e in x if isinstance(e, basestring)]), 
         axis=1) 

Dla każdego wiersza wyodrębnij elementy ciągów i dołącz do nich.

In [44]: df 
Out[44]: 
    ID_1 ID_2 ID_3 Combined_ID 
0 abc NaN NaN   abc 
1 NaN def NaN   def 
2 NaN NaN ghi   ghi 
3 NaN NaN jkl   jkl 
4 NaN mno NaN   mno 
5 pqr NaN NaN   pqr 

Podobała mi się odpowiedź @ EdChum i wygląda na bardziej czytelną.

Metoda jest kosztowna dla tych mniejszych danych.

In [45]: %timeit df.fillna('').sum(axis=1) 
1000 loops, best of 3: 808 µs per loop 

In [46]: %timeit df.apply(lambda x : ''.join([e for e in x if isinstance(e, basestring)]), axis=1) 
1000 loops, best of 3: 285 µs per loop 

Bo ['ID_1','ID_2','ID_3'] kolumny tylko

df[['ID_1','ID_2','ID_3']].apply(lambda_function) 
+0

To nie jest takie zaskakujące, ale 'apply' nie skaluje się dobrze, po prostu zrobiłem timing na 600 wierszowym df, a czasy były 6.24ms vs 33,3ms porównując moją metodę z twoimi, oczekuję, że różnica wydajności znacznie wzrośnie na dużo większym zestawy danych – EdChum

+0

Czy istnieje sposób na określenie tylko trzech kolumn, których potrzebuję? W ten sposób są dołączane inne niepowiązane kolumny. – EMC

+0

@EdChum Absolutnie, 'apply' nie działa dobrze na większych zestawach danych. Więc wspomniałem * drogie dla tych mniejszych danych. * =) – Zero

12

można wykorzystywać tę właściwość, że podsumowujący będzie złączyć wartości ciągów, więc można zadzwonić fillna i przekazać pusty str i połączenia sum i przekazać param axis=1 do sumy w wierszach:

In [26]: 

df['Combined_ID'] = df.fillna('').sum(axis=1) 
df 
Out[26]: 
    ID_1 ID_2 ID_3 Combined_ID 
0 abc NaN NaN   abc 
1 NaN def NaN   def 
2 NaN NaN ghi   ghi 
3 NaN NaN jkl   jkl 
4 NaN mno NaN   mno 
5 pqr NaN NaN   pqr 

Jeśli interesują Cię tylko te 3 kolumny, możesz je wybrać:

In [39]: 

df['Combined_ID'] = df[['ID_1','ID_2','ID_3']].fillna('').sum(axis=1) 
df 
Out[39]: 
    ID_1 ID_2 ID_3 Combined_ID 
0 abc NaN NaN   abc 
1 NaN def NaN   def 
2 NaN NaN ghi   ghi 
3 NaN NaN jkl   jkl 
4 NaN mno NaN   mno 
5 pqr NaN NaN   pqr 
+0

'df.max (axis = 1)' zrobiłby bez potrzeby "fillna", jak sądzę. – piroot

Powiązane problemy