Pandas의 일부 열에 있는 값을 기반으로 DataFrame
에서 행을 선택하려면 어떻게 해야 합니까?
SQL에서는 다음을 사용합니다.
SELECT * FROM table WHERE colume_name = some_value
Pandas의 문서를 보려고 했지만 즉시 답을 찾지 못했습니다.
질문자 :szli
Pandas의 일부 열에 있는 값을 기반으로 DataFrame
에서 행을 선택하려면 어떻게 해야 합니까?
SQL에서는 다음을 사용합니다.
SELECT * FROM table WHERE colume_name = some_value
Pandas의 문서를 보려고 했지만 즉시 답을 찾지 못했습니다.
some_value
와 같은 행을 선택하려면 ==
사용하십시오.
df.loc[df['column_name'] == some_value]
some_values
에 있는 행을 선택하려면 isin
사용하십시오.
df.loc[df['column_name'].isin(some_values)]
여러 조건을 &
결합:
df.loc[(df['column_name'] >= A) & (df['column_name'] <= B)]
괄호에 유의하십시오. Python의연산자 우선 순위 규칙 &
<=
및 >=
보다 더 밀접하게 바인딩됩니다. 따라서 마지막 예의 괄호가 필요합니다. 괄호 없이
df['column_name'] >= A & df['column_name'] <= B
다음과 같이 구문 분석됩니다.
df['column_name'] >= (A & df['column_name']) <= B
Series 의 Truth 값이 되는 결과는 모호한 오류입니다.
some_value
와 같지 않은 행을 선택하려면 !=
사용하십시오.
df.loc[df['column_name'] != some_value]
isin
은 부울 계열을 반환하므로 값이 some_values
없는 ~
사용하여 부울 계열을 무효화합니다.
df.loc[~df['column_name'].isin(some_values)]
예를 들어,
import pandas as pd import numpy as np df = pd.DataFrame({'A': 'foo bar foo bar foo bar foo foo'.split(), 'B': 'one one two three two two one three'.split(), 'C': np.arange(8), 'D': np.arange(8) * 2}) print(df) # ABCD # 0 foo one 0 0 # 1 bar one 1 2 # 2 foo two 2 4 # 3 bar three 3 6 # 4 foo two 4 8 # 5 bar two 5 10 # 6 foo one 6 12 # 7 foo three 7 14 print(df.loc[df['A'] == 'foo'])
수익률
ABCD 0 foo one 0 0 2 foo two 2 4 4 foo two 4 8 6 foo one 6 12 7 foo three 7 14
포함하려는 값이 여러 개인 경우 목록(또는 더 일반적으로 반복 가능한 모든 값)에 넣고 isin
사용합니다.
print(df.loc[df['B'].isin(['one','three'])])
수익률
ABCD 0 foo one 0 0 1 bar one 1 2 3 bar three 3 6 6 foo one 6 12 7 foo three 7 14
그러나 이 작업을 여러 번 수행하려면 먼저 인덱스를 만든 다음 df.loc
을 사용하는 것이 더 효율적입니다.
df = df.set_index(['B']) print(df.loc['one'])
수익률
ACD B one foo 0 0 one bar 1 2 one foo 6 12
또는 인덱스의 여러 값을 포함하려면 df.index.isin
사용하십시오.
df.loc[df.index.isin(['one','two'])]
수익률
ACD B one foo 0 0 one bar 1 2 two foo 2 4 two foo 4 8 two bar 5 10 one foo 6 12
Pandas 데이터 프레임에서 행을 선택하는 방법에는 여러 가지가 있습니다.
df[df['col'] == value
] )df.iloc[...]
)df.xs(...)
)df.query(...)
API 아래에서는 특정 기술을 언제 사용해야 하는지에 대한 조언과 함께 각각의 예를 보여 드리겠습니다. 기준이 열 'A'
== 'foo'
(성능에 대한 참고 사항: 각 기본 유형에 대해 Pandas API를 사용하여 작업을 단순하게 유지하거나 API 외부(일반적으로 NumPy로 이동하여 속도를 높일 수 있습니다.)
설정
가장 먼저 필요한 것은 행 선택 기준으로 작용할 조건을 식별하는 것입니다. OP의 경우 column_name == some_value
로 시작하고 다른 일반적인 사용 사례를 포함합니다.
@unutbu에서 차용:
import pandas as pd, numpy as np df = pd.DataFrame({'A': 'foo bar foo bar foo bar foo foo'.split(), 'B': 'one one two three two two one three'.split(), 'C': np.arange(8), 'D': np.arange(8) * 2})
... 부울 인덱싱을 위해서는 각 행의 'A'
열이 'foo'
와 같은 실제 값을 찾은 다음 해당 진리 값을 사용하여 유지할 행을 식별해야 합니다. 일반적으로 이 시리즈의 이름은 진리값 배열인 mask
입니다. 우리는 여기에서도 그렇게 할 것입니다.
mask = df['A'] == 'foo'
그런 다음 이 마스크를 사용하여 데이터 프레임을 슬라이스하거나 인덱싱할 수 있습니다.
df[mask] ABCD 0 foo one 0 0 2 foo two 2 4 4 foo two 4 8 6 foo one 6 12 7 foo three 7 14
이것은 이 작업을 수행하는 가장 간단한 방법 중 하나이며 성능이나 직관성이 문제가 아닌 경우 선택한 방법이어야 합니다. mask
를 만드는 다른 방법을 고려할 수 있습니다.
위치 인덱싱( df.iloc[...]
)에는 사용 사례가 있지만 이것은 그 중 하나가 아닙니다. 슬라이스할 위치를 식별하려면 먼저 위에서 수행한 것과 동일한 부울 분석을 수행해야 합니다. 이렇게 하면 동일한 작업을 수행하기 위해 하나의 추가 단계를 수행할 수 있습니다.
mask = df['A'] == 'foo' pos = np.flatnonzero(mask) df.iloc[pos] ABCD 0 foo one 0 0 2 foo two 2 4 4 foo two 4 8 6 foo one 6 12 7 foo three 7 14
레이블 인덱싱은 매우 편리할 수 있지만, 이 경우에는 이익 없이 더 많은 작업을 다시 수행합니다.
df.set_index('A', append=True, drop=False).xs('foo', level=1) ABCD 0 foo one 0 0 2 foo two 2 4 4 foo two 4 8 6 foo one 6 12 7 foo three 7 14
df.query()
API pd.DataFrame.query
는 이 작업을 수행하는 매우 우아하고 직관적인 방법이지만 종종 느립니다. 그러나 아래의 타이밍에 주의하면 대용량 데이터의 경우 쿼리가 매우 효율적입니다. 표준 접근 방식보다 더 많고 내 최선의 제안과 비슷한 규모입니다.
df.query('A == "foo"') ABCD 0 foo one 0 0 2 foo two 2 4 4 foo two 4 8 6 foo one 6 12 7 foo three 7 14
Boolean
mask
를 사용하는 것입니다.
Boolean
mask
만드는 방법을 수정하여 실제 개선을 할 수 있습니다.
mask
대안 1 기본 NumPy 배열을 사용하고 다른 pd.Series
mask = df['A'].values == 'foo'
마지막에 더 완전한 시간 테스트를 보여주겠지만 샘플 데이터 프레임을 사용하여 얻을 수 있는 성능 향상을 살펴보십시오. mask
생성의 차이점을 살펴봅니다.
%timeit mask = df['A'].values == 'foo' %timeit mask = df['A'] == 'foo' 5.84 µs ± 195 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each) 166 µs ± 4.45 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
mask
를 평가하는 것은 30배 더 빠릅니다. 이는 부분적으로 NumPy 평가가 더 빠른 경우가 많기 때문입니다. pd.Series
개체를 빌드하는 데 필요한 오버헤드가 부족하기 때문입니다.
mask
와 다른 마스크로 슬라이싱하는 타이밍을 살펴보겠습니다.
mask = df['A'].values == 'foo' %timeit df[mask] mask = df['A'] == 'foo' %timeit df[mask] 219 µs ± 12.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each) 239 µs ± 7.03 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
성능 향상은 그렇게 뚜렷하지 않습니다. 이것이 더 강력한 테스트를 통해 유지되는지 확인할 것입니다.
mask
대안 2 우리는 데이터 프레임도 재구성할 수 있었습니다. 데이터 프레임을 재구성할 때 큰 경고가 있습니다. 그렇게 할 때 dtypes
df[mask]
대신에 이것을 할 것입니다.
pd.DataFrame(df.values[mask], df.index[mask], df.columns).astype(df.dtypes)
데이터 프레임이 우리의 예와 같이 혼합 유형인 경우 df.values
를 얻을 때 결과 배열은 dtype
object
이고 결과적으로 새 데이터 프레임의 모든 열은 dtype
object
됩니다. astype(df.dtypes)
필요하고 잠재적인 성능 향상이 중단됩니다.
%timeit df[m] %timeit pd.DataFrame(df.values[mask], df.index[mask], df.columns).astype(df.dtypes) 216 µs ± 10.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each) 1.43 ms ± 39.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
그러나 데이터 프레임이 혼합 유형이 아닌 경우 매우 유용한 방법입니다.
주어진
np.random.seed([3,1415]) d1 = pd.DataFrame(np.random.randint(10, size=(10, 5)), columns=list('ABCDE')) d1 ABCDE 0 0 2 7 3 8 1 7 0 6 8 6 2 0 2 0 4 9 3 7 3 2 4 3 4 3 6 7 7 4 5 5 3 7 5 9 6 8 7 6 4 7 7 6 2 6 6 5 8 2 8 7 5 8 9 4 7 6 1 5
%%timeit mask = d1['A'].values == 7 d1[mask] 179 µs ± 8.73 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
대
%%timeit mask = d1['A'].values == 7 pd.DataFrame(d1.values[mask], d1.index[mask], d1.columns) 87 µs ± 5.12 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
우리는 시간을 반으로 줄였습니다.
mask
대안 3
또한 방송 @unutbu 미국 사용 방법 pd.Series.isin
각 요소를 고려하여 df['A']
값들의 세트에있는. 이것은 우리의 값 집합이 하나의 값 집합인 'foo'
경우 동일한 것으로 평가됩니다. 그러나 필요한 경우 더 큰 값 집합을 포함하도록 일반화하기도 합니다. 이것은 더 일반적인 솔루션임에도 불구하고 여전히 꽤 빠릅니다. 유일한 진정한 손실은 개념에 익숙하지 않은 사람들의 직관성입니다.
mask = df['A'].isin(['foo']) df[mask] ABCD 0 foo one 0 0 2 foo two 2 4 4 foo two 4 8 6 foo one 6 12 7 foo three 7 14
그러나 이전과 마찬가지로 NumPy를 사용하여 사실상 아무 것도 희생하지 않으면서 성능을 향상시킬 수 있습니다. 우리는 np.in1d
mask = np.in1d(df['A'].values, ['foo']) df[mask] ABCD 0 foo one 0 0 2 foo two 2 4 4 foo two 4 8 6 foo one 6 12 7 foo three 7 14
타이밍
다른 게시물에서 언급한 다른 개념도 참조용으로 포함하겠습니다.
아래 코드
이 테이블의 각 열 은 각 기능을 테스트하는 다른 길이의 데이터 프레임을 나타냅니다. 1.0
때 가장 빠른 함수를 사용하여 상대적인 소요 시간을 보여줍니다.
res.div(res.min()) 10 30 100 300 1000 3000 10000 30000 mask_standard 2.156872 1.850663 2.034149 2.166312 2.164541 3.090372 2.981326 3.131151 mask_standard_loc 1.879035 1.782366 1.988823 2.338112 2.361391 3.036131 2.998112 2.990103 mask_with_values 1.010166 1.000000 1.005113 1.026363 1.028698 1.293741 1.007824 1.016919 mask_with_values_loc 1.196843 1.300228 1.000000 1.000000 1.038989 1.219233 1.037020 1.000000 query 4.997304 4.765554 5.934096 4.500559 2.997924 2.397013 1.680447 1.398190 xs_label 4.124597 4.272363 5.596152 4.295331 4.676591 5.710680 6.032809 8.950255 mask_with_isin 1.674055 1.679935 1.847972 1.724183 1.345111 1.405231 1.253554 1.264760 mask_with_in1d 1.000000 1.083807 1.220493 1.101929 1.000000 1.000000 1.000000 1.144175
mask_with_values
와 mask_with_in1d
간에 공유되는 것처럼 보입니다.
res.T.plot(loglog=True)
기능
def mask_standard(df): mask = df['A'] == 'foo' return df[mask] def mask_standard_loc(df): mask = df['A'] == 'foo' return df.loc[mask] def mask_with_values(df): mask = df['A'].values == 'foo' return df[mask] def mask_with_values_loc(df): mask = df['A'].values == 'foo' return df.loc[mask] def query(df): return df.query('A == "foo"') def xs_label(df): return df.set_index('A', append=True, drop=False).xs('foo', level=-1) def mask_with_isin(df): mask = df['A'].isin(['foo']) return df[mask] def mask_with_in1d(df): mask = np.in1d(df['A'].values, ['foo']) return df[mask]
테스트
res = pd.DataFrame( index=[ 'mask_standard', 'mask_standard_loc', 'mask_with_values', 'mask_with_values_loc', 'query', 'xs_label', 'mask_with_isin', 'mask_with_in1d' ], columns=[10, 30, 100, 300, 1000, 3000, 10000, 30000], dtype=float ) for j in res.columns: d = pd.concat([df] * j, ignore_index=True) for i in res.index:a stmt = '{}(d)'.format(i) setp = 'from __main__ import d, {}'.format(i) res.at[i, j] = timeit(stmt, setp, number=50)
특별한 타이밍
전체 데이터 프레임에 대해 dtype
이 있는 특수한 경우를 살펴봅니다.
아래 코드
spec.div(spec.min()) 10 30 100 300 1000 3000 10000 30000 mask_with_values 1.009030 1.000000 1.194276 1.000000 1.236892 1.095343 1.000000 1.000000 mask_with_in1d 1.104638 1.094524 1.156930 1.072094 1.000000 1.000000 1.040043 1.027100 reconstruct 1.000000 1.142838 1.000000 1.355440 1.650270 2.222181 2.294913 3.406735
수백 행을 넘어서면 재구성할 가치가 없다는 것이 밝혀졌습니다.
spec.T.plot(loglog=True)
기능
np.random.seed([3,1415]) d1 = pd.DataFrame(np.random.randint(10, size=(10, 5)), columns=list('ABCDE')) def mask_with_values(df): mask = df['A'].values == 'foo' return df[mask] def mask_with_in1d(df): mask = np.in1d(df['A'].values, ['foo']) return df[mask] def reconstruct(df): v = df.values mask = np.in1d(df['A'].values, ['foo']) return pd.DataFrame(v[mask], df.index[mask], df.columns) spec = pd.DataFrame( index=['mask_with_values', 'mask_with_in1d', 'reconstruct'], columns=[10, 30, 100, 300, 1000, 3000, 10000, 30000], dtype=float )
테스트
for j in spec.columns: d = pd.concat([df] * j, ignore_index=True) for i in spec.index: stmt = '{}(d)'.format(i) setp = 'from __main__ import d, {}'.format(i) spec.at[i, j] = timeit(stmt, setp, number=50)
판다 등가
select * from table where column_name = some_value
~이다
table[table.column_name == some_value]
여러 조건:
table[(table.column_name == some_value) | (table.column_name2 == some_value2)]
또는
table.query('column_name == some_value | column_name2 == some_value2')
import pandas as pd # Create data set d = {'foo':[100, 111, 222], 'bar':[333, 444, 555]} df = pd.DataFrame(d) # Full dataframe: df # Shows: # bar foo # 0 333 100 # 1 444 111 # 2 555 222 # Output only the row(s) in df where foo is 222: df[df.foo == 222] # Shows: # bar foo # 2 555 222
위의 코드에서 df[df.foo == 222]
행은 열 값(이 경우 222
을 기반으로 행을 제공합니다.
여러 조건도 가능합니다.
df[(df.foo == 222) | (df.bar == 444)] # bar foo # 1 444 111 # 2 555 222
그러나 그 시점에서 쿼리 기능을 사용하는 것이 좋습니다. 덜 장황하고 동일한 결과를 산출하기 때문입니다.
df.query('foo == 222 | bar == 444')
이전 답변의 구문이 중복되고 기억하기 어렵다는 것을 알았습니다. Pandas는 query()
메서드를 도입했으며 저는 이 메서드를 훨씬 선호합니다. 귀하의 질문에 대해 df.query('col == val')
http://pandas.pydata.org/pandas-docs/version/0.17.0/indexing.html#indexing-query 에서 재생산
In [167]: n = 10 In [168]: df = pd.DataFrame(np.random.rand(n, 3), columns=list('abc')) In [169]: df Out[169]: abc 0 0.687704 0.582314 0.281645 1 0.250846 0.610021 0.420121 2 0.624328 0.401816 0.932146 3 0.011763 0.022921 0.244186 4 0.590198 0.325680 0.890392 5 0.598892 0.296424 0.007312 6 0.634625 0.803069 0.123872 7 0.924168 0.325076 0.303746 8 0.116822 0.364564 0.454607 9 0.986142 0.751953 0.561512 # pure python In [170]: df[(df.a < df.b) & (df.b < df.c)] Out[170]: abc 3 0.011763 0.022921 0.244186 8 0.116822 0.364564 0.454607 # query In [171]: df.query('(a < b) & (b < c)') Out[171]: abc 3 0.011763 0.022921 0.244186 8 0.116822 0.364564 0.454607
@
를 추가하여 환경의 변수에 액세스할 수도 있습니다.
exclude = ('red', 'orange') df.query('color not in @exclude')
.query
를 사용하여 유연성 향상:2019년 8월 업데이트된 답변
pandas >= 0.25.0 이후로 query
메서드를 사용하여 pandas 메서드와 공백이 있는 열 이름으로 데이터 프레임을 필터링할 수 있습니다. 일반적으로 열 이름에 공백이 있으면 오류가 발생하지만 이제 역따옴표(`)를 사용하여 해결할 수 있습니다 . GitHub 참조:
# Example dataframe df = pd.DataFrame({'Sender email':['ex@example.com', "reply@shop.com", "buy@shop.com"]}) Sender email 0 ex@example.com 1 reply@shop.com 2 buy@shop.com
사용 .query
방법으로 str.endswith
:
df.query('`Sender email`.str.endswith("@shop.com")')
산출
Sender email 1 reply@shop.com 2 buy@shop.com
또한 쿼리에서 @
접두사로 지역 변수를 사용할 수 있습니다.
domain = 'shop.com' df.query('`Sender email`.str.endswith(@domain)')
산출
Sender email 1 reply@shop.com 2 buy@shop.com
numpy.where를 사용하면 더 빠른 결과를 얻을 수 있습니다.
예를 들어, unubtu의 설정으로 -
In [76]: df.iloc[np.where(df.A.values=='foo')] Out[76]: ABCD 0 foo one 0 0 2 foo two 2 4 4 foo two 4 8 6 foo one 6 12 7 foo three 7 14
타이밍 비교:
In [68]: %timeit df.iloc[np.where(df.A.values=='foo')] # fastest 1000 loops, best of 3: 380 µs per loop In [69]: %timeit df.loc[df['A'] == 'foo'] 1000 loops, best of 3: 745 µs per loop In [71]: %timeit df.loc[df['A'].isin(['foo'])] 1000 loops, best of 3: 562 µs per loop In [72]: %timeit df[df.A=='foo'] 1000 loops, best of 3: 796 µs per loop In [74]: %timeit df.query('(A=="foo")') # slowest 1000 loops, best of 3: 1.71 ms per loop
다음은 간단한 예입니다.
from pandas import DataFrame # Create data set d = {'Revenue':[100,111,222], 'Cost':[333,444,555]} df = DataFrame(d) # mask = Return True when the value in column "Revenue" is equal to 111 mask = df['Revenue'] == 111 print mask # Result: # 0 False # 1 True # 2 False # Name: Revenue, dtype: bool # Select * FROM df WHERE Revenue = 111 df[mask] # Result: # Cost Revenue # 1 444 111
Pandas의 주어진 값에 대해 여러 열 중 특정 열만 선택하는 경우:
select col_name1, col_name2 from table where column_name = some_value.
옵션 loc
:
df.loc[df['column_name'] == some_value, [col_name1, col_name2]]
또는 query
:
df.query('column_name == some_value')[[col_name1, col_name2]]
이 유명한 질문에 추가하려면(조금 늦었지만): df.groupby('column_name').get_group('column_desired_value').reset_index()
를 수행하여 특정 값을 갖는 지정된 열로 새 데이터 프레임을 만들 수도 있습니다. . 예
import pandas as pd df = pd.DataFrame({'A': 'foo bar foo bar foo bar foo foo'.split(), 'B': 'one one two three two two one three'.split()}) print("Original dataframe:") print(df) b_is_two_dataframe = pd.DataFrame(df.groupby('B').get_group('two').reset_index()).drop('index', axis = 1) #NOTE: the final drop is to remove the extra index column returned by groupby object print('Sub dataframe where B is two:') print(b_is_two_dataframe)
실행하면 다음이 제공됩니다.
Original dataframe: AB 0 foo one 1 bar one 2 foo two 3 bar three 4 foo two 5 bar two 6 foo one 7 foo three Sub dataframe where B is two: AB 0 foo two 1 foo two 2 bar two
문서에서 영감을 얻은 최신 버전의 Pandas( 데이터 보기 ):
df[df["colume_name"] == some_value] #Scalar, True/False.. df[df["colume_name"] == "some_value"] #String
절을 괄호 ()
&
및 |
결합하여 여러 조건을 결합합니다. (및/또는). 이와 같이:
df[(df["colume_name"] == "some_value1") & (pd[pd["colume_name"] == "some_value2"])]
기타 필터
pandas.notna(df["colume_name"]) == True # Not NaN df['colume_name'].str.contains("text") # Search for "text" df['colume_name'].str.lower().str.contains("text") # Search for "text", after converting to lowercase
.apply를 사용할 수도 있습니다.
df.apply(lambda row: row[df['B'].isin(['one','three'])])
실제로는 행 단위로 작동합니다(즉, 각 행에 함수를 적용함).
출력은
ABCD 0 foo one 0 0 1 bar one 1 2 3 bar three 3 6 6 foo one 6 12 7 foo three 7 14
결과는 @unutbu가 언급한 대로 사용하는 것과 동일합니다.
df[[df['B'].isin(['one','three'])]]
출처 : http:www.stackoverflow.com/questions/17071871/how-do-i-select-rows-from-a-dataframe-based-on-column-values
Python에서 파일 또는 폴더를 삭제하는 방법은 무엇입니까? (0) | 2021.11.09 |
---|---|
JavaScript에서 "undefined"를 어떻게 확인할 수 있습니까? [복제하다] (0) | 2021.11.09 |
병합 충돌이 발생했습니다. 병합을 어떻게 중단할 수 있습니까? (0) | 2021.11.09 |
__init__.py는 무엇을 위한 것입니까? (0) | 2021.11.09 |
이미 Git 저장소에 커밋된 파일 무시 [중복] (0) | 2021.11.09 |