2017-08-03 23 views
13

Próbuję wyciąć ramkę danych na podstawie listy wartości, w jaki sposób mogę to zrobić?Powróć podzbiór na podstawie listy wartości logicznych

Powiedzmy mam listę, L, i wygląda na to: [0,1,0,0,1,1,0,0,0,1]

Chcę zwrócić wszystkie wiersze w dataframe, df, na podstawie, jeżeli wartość na liście jest 1. W tym przykładzie, Chciałbym dodać wiersze, w których indeks wynosi 1, 4, 5 i 9. Czy jest to łatwy sposób? Przepraszam, jeśli jest to łatwe pytanie, ale wciąż przyzwyczaję się do danych.

+0

[tutaj] (https://stackoverflow.com/help/someone-answers) jest coś do rozważenia, jeśli otrzymali cenne odpowiedzi. – vestland

Odpowiedz

16

Można użyć maskowania tutaj:

df[np.array([0,1,0,0,1,1,0,0,0,1],dtype=bool)] 

więc skonstruować tablicę logiczną true i false. Każde miejsce, w którym tablica jest prawdziwa, to wiersz, który wybieramy.

Pamiętaj, że wykonujemy nie filtrowanie w miejscu. W celu odzyskania wynik, trzeba przypisać wynik do (ewentualnie inny) Zmienna:

df2 = df[np.array([0,1,0,0,1,1,0,0,0,1],dtype=bool)] 
13

Konwersja listy do tablicy logicznej, a następnie użyć logiczną indeksowania:

df = pd.DataFrame(np.random.randint(10, size=(10, 3))) 

df[np.array(lst).astype(bool)] 
Out: 
    0 1 2 
1 8 6 3 
4 2 7 3 
5 7 2 3 
9 1 3 4 
11

konfiguracji
setup zapożyczonych @ ayhan za

df = pd.DataFrame(np.random.randint(10, size=(10, 3))) 

Bez numpy
nie najszybszy, ale ma swój własny i jest zdecydowanie najkrótszy.

df[list(map(bool, lst))] 

    0 1 2 
1 3 5 6 
4 6 3 2 
5 5 7 6 
9 0 0 1 

Czas

results.div(results.min(1), 0).round(2).pipe(lambda d: d.assign(Best=d.idxmin(1))) 

     ayh wvo pir mxu wen Best 
N           
1  1.53 1.00 1.02 4.95 2.61 wvo 
3  1.06 1.00 1.04 5.46 2.84 wvo 
10  1.00 1.00 1.00 4.30 2.73 ayh 
30  1.00 1.05 1.24 4.06 3.76 ayh 
100  1.16 1.00 1.19 3.90 3.53 wvo 
300  1.29 1.00 1.32 2.50 2.38 wvo 
1000 1.54 1.00 2.19 2.24 3.85 wvo 
3000 1.39 1.00 2.17 1.81 4.55 wvo 
10000 1.22 1.00 2.21 1.35 4.36 wvo 
30000 1.19 1.00 2.26 1.39 5.36 wvo 
100000 1.19 1.00 2.19 1.31 4.82 wvo 

fig, (a1, a2) = plt.subplots(2, 1, figsize=(6, 6)) 
results.plot(loglog=True, lw=3, ax=a1) 
results.div(results.min(1), 0).round(2).plot.bar(logy=True, ax=a2) 
fig.tight_layout() 

enter image description here


Kod Testowanie

ayh = lambda d, l: d[np.array(l).astype(bool)] 
wvo = lambda d, l: d[np.array(l, dtype=bool)] 
pir = lambda d, l: d[list(map(bool, l))] 
wen = lambda d, l: d.loc[[i for i, x in enumerate(l) if x == 1], :] 

def mxu(d, l): 
    a = np.array(l) 
    return d.query('@a != 0') 

results = pd.DataFrame(
    index=pd.Index([1, 3, 10, 30, 100, 300, 
        1000, 3000, 10000, 30000, 100000], name='N'), 
    columns='ayh wvo pir mxu wen'.split(), 
    dtype=float 
) 

for i in results.index: 
    d = pd.concat([df] * i, ignore_index=True) 
    l = lst * i 
    for j in results.columns: 
     stmt = '{}(d, l)'.format(j) 
     setp = 'from __main__ import d, l, {}'.format(j) 
     results.set_value(i, j, timeit(stmt, setp, number=10)) 
+0

Czy mógłbyś przetestować 'df.loc [[i na i, x w wyliczeniu (lst), jeśli x == 1] ,:]', powinien być najwolniejszy, ale ciekawy jak powolny będzie ... – Wen

+0

@Sen Zaktualizowałem – piRSquared

+0

Dziękuję ~ Moja jest najgorsza bez wątpienia T_T – Wen

7

kolejny "twórcze" podejście:

In [181]: a = np.array(lst) 

In [182]: df.query("index * @a > 0") 
Out[182]: 
    0 1 2 
1 1 5 5 
4 0 2 0 
5 4 9 9 
9 2 2 5 

lub much better variant from @ayhan:

In [183]: df.query("@a != 0") 
Out[183]: 
    0 1 2 
1 1 5 5 
4 0 2 0 
5 4 9 9 
9 2 2 5 

PS Ja również zapożyczone @ konfiguracji ayhan za

+1

Czy "df.query (" @ a> 0 ") nie wystarczy? – ayhan

+1

@ayhan, tak, rzeczywiście, dziękuję! Wygląda o wiele czystsze. – MaxU

4

Or może znaleźć pozycję 1 w list i plasterek z Wybieranie Dataframe

df.loc[[i for i,x in enumerate(lst) if x == 1],:] 
1

podstawie listy zawierającej wartości logiczne jest coś itertools.compress robi dobrze.

Biorąc

>>> df = pd.DataFrame(np.random.randint(10, size=(10, 2))) 
>>> selectors = [0, 1, 0, 0, 1, 1, 0, 0, 0, 1] 

Kod

>>> selected_idxs = list(itertools.compress(df.index, selectors)) # [1, 4, 5, 9] 
>>> df.iloc[selected_idxs, :] 
    0 1 
1 1 9 
4 3 4 
5 4 1 
9 8 9