python - 프레임 - 판다 스 열 인덱싱




판다의 열 값을 기반으로 DataFrame에서 행 선택 (8)

tl; dr

판다는

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

위의 코드에서이 경우에는 행 값 222 를 기준으로 행을 제공하는 줄은 df[df.foo == 222] 입니다.

여러 조건이 가능합니다.

df[(df.foo == 222) | (df.bar == 444)]
#    bar  foo
# 1  444  111
# 2  555  222

그러나 그 시점에서 query 함수를 사용하는 것이 좋습니다. 왜냐하면 query 함수는 덜 장황하고 동일한 결과를 산출하기 때문입니다.

df.query('foo == 222 | bar == 444')

pandas의 일부 열 값을 기반으로 DataFrame에서 행을 선택하는 방법은 무엇입니까?
SQL에서는 다음을 사용합니다.

select * from table where colume_name = some_value. 

나는 판다 문서를 보려고했지만 대답을 즉시 찾지 못했습니다.


다음은 간단한 예제입니다.

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

열 값이 스칼라, some_value 와 같은 행을 선택하려면 == 사용하십시오.

df.loc[df['column_name'] == some_value]

열 값이 iterable, some_values 에있는 행을 선택하려면 isin 사용하십시오.

df.loc[df['column_name'].isin(some_values)]

& 와 여러 조건 결합 :

df.loc[(df['column_name'] == some_value) & df['other_column'].isin(some_values)]

열 값 some_value 가 아닌 행을 선택하려면 != :를 사용하십시오.

df.loc[df['column_name'] != some_value]

isin 은 부울 Series를 반환하므로 값이 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)
#      A      B  C   D
# 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'])

산출량

     A      B  C   D
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'])])

산출량

     A      B  C   D
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.loc 을 사용하는 것이 더 효율적입니다.

df = df.set_index(['B'])
print(df.loc['one'])

산출량

       A  C   D
B              
one  foo  0   0
one  bar  1   2
one  foo  6  12

또는 인덱스의 여러 값을 포함 시키려면 df.index.isin 사용 df.index.isin .

df.loc[df.index.isin(['one','two'])]

산출량

       A  C   D
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

열의 값이 값의 목록이 아닌 값을 포함하여 데이터 프레임의 행을 선택하려고 한 경우 위의 값 목록에 대해 unutbu의 대답을 뒤집는 방법은 다음과 같습니다.

df.loc[~df['column_name'].isin(some_values)]

(단 하나의 값을 포함시키지 않으려면 보통 등호 연산자 != .)를 사용하십시오.

예:

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(df)

우리에게 주어지다

     A      B
0  foo    one
1  bar    one
2  foo    two
3  bar  three
4  foo    two
5  bar    two
6  foo    one
7  foo  three    

B 에서 one 또는 three 아닌 행만 하위 집합으로 만들려면 다음과 같이하십시오.

df.loc[~df['B'].isin(['one', 'three'])]

산출량

     A    B
2  foo  two
4  foo  two
5  bar  two

판다에서 주어진 값에 대해 여러 열 중에서 특정 열만 선택하는 경우 :

select col_name1, col_name2 from table where column_name = some_value.

옵션 :

df.loc[df['column_name'] == some_value][[col_name1, col_name2]]

또는

df.query['column_name' == 'some_value'][[col_name1, col_name2]]

팬더 데이터 프레임에서 행을 선택하는 몇 가지 기본 방법이 있습니다.

  1. 부울 색인 생성
  2. 위치 인덱싱
  3. 레이블 색인 생성
  4. API

각 기본 유형에 대해 우리는 팬더 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'

1.
불린 색인은 각 행의 'A' 열이 'foo' 와 같은 진리 값을 찾은 다음 그 진리 값을 사용하여 보관할 행을 식별해야합니다. 일반적으로이 시리즈의 이름은 진리 값의 배열 인 mask 입니다. 우리는 여기서도 그렇게 할 것입니다.

mask = df['A'] == 'foo'

그런 다음이 마스크를 사용하여 데이터 프레임을 슬라이스 또는 색인화 할 수 있습니다.

df[mask]

     A      B  C   D
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 를 만드는 다른 방법을 고려할 수 있습니다.

2.
위치 인덱싱은 유스 케이스를 가지고 있지만 이것도 그 중 하나가 아닙니다. 분할 할 위치를 식별하려면 먼저 위에서 수행 한 것과 동일한 부울 분석을 수행해야합니다. 이로 인해 동일한 작업을 수행하기위한 추가 단계가 수행됩니다.

mask = df['A'] == 'foo'
pos = np.flatnonzero(mask)
df.iloc[pos]

     A      B  C   D
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)

     A      B  C   D
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

4.
pd.DataFrame.query 는이 작업을 수행하는 데 매우 우아하고 직관적 인 방법입니다. 그러나 종종 더 느립니다. 그러나 큰 데이터의 경우 아래의 타이밍에주의를 기울이면 쿼리가 매우 효율적입니다. 내 제안에 비해 표준 접근 방식과 비슷한 수준입니다.

df.query('A == "foo"')

     A      B  C   D
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 를 작성하는 오버 헤드는 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)

numpy 배열로 mask 를 평가하는 것이 ~ 30 배 빠릅니다. 이것은 부분적으로 numpy 평가가 종종 더 빠르기 때문입니다. 또한 부분적으로는 색인 및 해당 pd.Series 오브젝트를 빌드하는 데 필요한 오버 헤드 부족 때문 pd.Series 합니다.

다음으로 한 mask 로 다른 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 결과적으로 새 데이터 프레임의 모든 열은 dtype object 됩니다. 따라서 astype(df.dtypes) 필요하며 잠재적 인 성능 향상을 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

   A  B  C  D  E
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'] 의 각 요소를 설명하기 위해 pd.Series.isin 을 사용하는 방법을 보여줍니다. 우리의 값 집합이 하나의 값, 즉 'foo' 의 집합이라면 이것은 동일한 것으로 평가됩니다. 그러나 필요한 경우 더 큰 값 집합을 포함하도록 일반화됩니다. 더 일반적인 해결책인데도 여전히 빠릅니다. 유일한 실손은 개념에 익숙하지 않은 사람들을위한 직관력입니다.

mask = df['A'].isin(['foo'])
df[mask]

     A      B  C   D
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 사용 np.in1d

mask = np.in1d(df['A'].values, ['foo'])
df[mask]

     A      B  C   D
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_valuesmask_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 이있을 때 특별한 경우를 살펴 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)

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:
     A      B
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:
     A    B
0  foo  two
1  foo  two
2  bar  two

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})
df[df['A']=='foo']

OUTPUT:
   A      B  C   D
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






dataframe