Mam DataFrame:
import pandas as pd
import numpy as np
df = pd.DataFrame({'foo.aa': [1, 2.1, np.nan, 4.7, 5.6, 6.8],
'foo.fighters': [0, 1, np.nan, 0, 0, 0],
'foo.bars': [0, 0, 0, 0, 0, 1],
'bar.baz': [5, 5, 6, 5, 5.6, 6.8],
'foo.fox': [2, 4, 1, 0, 0, 5],
'nas.foo': ['NA', 0, 1, 0, 0, 0],
'foo.manchu': ['NA', 0, 0, 0, 0, 0],})
Chcę wybrać wartości 1 w kolumnach zaczynających się od foo.
. Czy jest na to lepszy sposób niż:
df2 = df[(df['foo.aa'] == 1)|
(df['foo.fighters'] == 1)|
(df['foo.bars'] == 1)|
(df['foo.fox'] == 1)|
(df['foo.manchu'] == 1)
]
Coś podobnego do pisania czegoś takiego:
df2= df[df.STARTS_WITH_FOO == 1]
Odpowiedź powinna wydrukować ramkę danych w następujący sposób:
bar.baz foo.aa foo.bars foo.fighters foo.fox foo.manchu nas.foo
0 5.0 1.0 0 0 2 NA NA
1 5.0 2.1 0 1 4 0 0
2 6.0 NaN 0 NaN 1 0 1
5 6.8 6.8 1 0 5 0 0
[4 rows x 7 columns]
Najprostszym sposobem jest użycie str bezpośrednio w nazwach kolumn, nie ma takiej potrzeby
pd.Series
df.loc[:,df.columns.str.startswith("foo")]
źródło
Na podstawie odpowiedzi @ EdChum możesz wypróbować następujące rozwiązanie:
df[df.columns[pd.Series(df.columns).str.contains("foo")]]
Będzie to bardzo pomocne, jeśli nie wszystkie kolumny, które chcesz wybrać, zaczynają się od
foo
. Ta metoda wybiera wszystkie kolumny, które zawierają podciągfoo
i można go umieścić w dowolnym miejscu nazwy kolumny.W istocie, wymieniłem
.startswith()
z.contains()
.źródło
Możesz wypróbować wyrażenie regularne tutaj, aby odfiltrować kolumny zaczynające się od „foo”
df.filter(regex='^foo*')
Jeśli potrzebujesz w swojej kolumnie napisu foo
df.filter(regex='foo*')
byłoby odpowiednie.
W następnym kroku możesz użyć
df[df.filter(regex='^foo*').values==1]
aby odfiltrować wiersze, w których jedna z wartości kolumny „foo *” to 1.
źródło
Moje rozwiązanie. Wydajność może być wolniejsza:
a = pd.concat(df[df[c] == 1] for c in df.columns if c.startswith('foo')) a.sort_index() bar.baz foo.aa foo.bars foo.fighters foo.fox foo.manchu nas.foo 0 5.0 1.0 0 0 2 NA NA 1 5.0 2.1 0 1 4 0 0 2 6.0 NaN 0 NaN 1 0 1 5 6.8 6.8 1 0 5 0 0
źródło
Inną opcją wyboru żądanych wpisów jest użycie
map
:df.loc[(df == 1).any(axis=1), df.columns.map(lambda x: x.startswith('foo'))]
co daje ci wszystkie kolumny dla wierszy zawierających
1
:foo.aa foo.bars foo.fighters foo.fox foo.manchu 0 1.0 0 0 2 NA 1 2.1 0 1 4 0 2 NaN 0 NaN 1 0 5 6.8 1 0 5 0
Selekcji wiersza dokonuje
(df == 1).any(axis=1)
jak w odpowiedzi @ ajcr, która daje:
0 True 1 True 2 True 3 False 4 False 5 True dtype: bool
co oznacza, że wiersz
3
i4
nie zawierają1
i nie zostaną wybrane.Wybór kolumn odbywa się za pomocą Boolean indeksowania tak:
df.columns.map(lambda x: x.startswith('foo'))
W powyższym przykładzie zwraca to
array([False, True, True, True, True, True, False], dtype=bool)
Jeśli więc kolumna nie zaczyna się od
foo
,False
jest zwracana, a zatem kolumna nie jest wybierana.Jeśli chcesz po prostu zwrócić wszystkie wiersze zawierające
1
- jak sugeruje żądane wyjście - możesz po prostu to zrobićdf.loc[(df == 1).any(axis=1)]
który powraca
bar.baz foo.aa foo.bars foo.fighters foo.fox foo.manchu nas.foo 0 5.0 1.0 0 0 2 NA NA 1 5.0 2.1 0 1 4 0 0 2 6.0 NaN 0 NaN 1 0 1 5 6.8 6.8 1 0 5 0 0
źródło
W moim przypadku potrzebowałem listy przedrostków
colsToScale=["production", "test", "development"] dc[dc.columns[dc.columns.str.startswith(tuple(colsToScale))]]
źródło