팬더 데이터 프레임에서 행의 하위 집합 수정


143

A와 B라는 두 개의 열이있는 팬더 DataFrame이 있다고 가정합니다. A가 0 일 때마다 B가 항상 NaN이되도록이 DataFrame을 수정하거나 복사본을 만들고 싶습니다. 어떻게하면 되나요?

나는 다음을 시도했다

df['A'==0]['B'] = np.nan

df['A'==0]['B'].values.fill(np.nan)

성공없이.


매우 빠른 솔루션을 찾고 있다면 아래 솔루션where 에서 볼 수있는 NumPy를 사용하십시오
Ted Petrou

답변:


243

사용 .loc레이블 기반 인덱싱 :

df.loc[df.A==0, 'B'] = np.nan

df.A==0표현식은 행을 색인화하고 열을 'B'선택 하는 부울 계열을 작성합니다 . 이를 사용하여 열의 하위 집합을 변환 할 수도 있습니다. 예 :

df.loc[df.A==0, 'B'] = df.loc[df.A==0, 'B'] / 2

나는 그것이 왜 작동하는지 정확히 알기 위해 팬더 내부에 대해 충분히 알지 못하지만 기본 문제는 때때로 DataFrame으로 인덱싱하면 결과의 사본을 반환하고 때로는 원래 객체에 대한보기를 반환한다는 것입니다. here 문서에 따르면 이 동작은 기본 numpy 동작에 따라 다릅니다. 한 작업 ([1] [2] 대신)으로 모든 것에 액세스하는 것이 설정 작업에 더 효과적이라는 것을 알았습니다.


이것의 두 번째 부분은 질문조차받지 않은 질문에 대한 좋은 대답입니다. ;-) 이것이 여전히 정식 팬더 답변인지 궁금합니다. 특히 b / c 그것은 명백한 DRY 위반입니다. 팬더 내부의 제약 조건에서 DRY를 위반하는 데 실제로 필요한가? (나는 이런 종류의 질문을 더 자세하게 게시 할 수 있지만, 그렇게하기 전에 빠른 답변이 있는지 확인하고 싶었습니다)
JohnE

열 이름이없는 데이터 프레임을 부분 집합으로 만드는 방법, 색인으로 df를 부분 집합으로 만드는 방법은 무엇입니까? df.loc [df [0] == 0]이 작동하지 않습니다 ... 대안은 무엇입니까? 감사합니다
amipro

89

고급 인덱싱에 대한 팬더 문서는 다음과 같습니다 .

이 섹션에서는 필요한 것을 정확하게 설명합니다! 알고 보니 df.loc(.ix가 사용되지 않습니다으로 - 아래 지적한 많은 같은) dataframe의 다이 싱 / 쿨 슬라이스 사용할 수 있습니다. 과. 또한 물건을 설정하는 데 사용될 수 있습니다.

df.loc[selection criteria, columns I want] = value

브렌의 대답은 말하고 그래서 '나에게 모든 장소 찾아 df.A == 0선택 열을 B하고로 설정 np.nan'


2
당신은 내 하루를 만들었습니다. 명확한 설명.
TwinPenguins

1
그래, 어떻게 든 loc[selection criteria, columns I want]당신의 마음에 완벽하게 붙어 ...
EmEs

29

팬더 0.20 ix 부터는 더 이상 사용되지 않습니다 . 올바른 방법은 df.loc 를 사용하는 것입니다

다음은 실제 예입니다

>>> import pandas as pd 
>>> import numpy as np 
>>> df = pd.DataFrame({"A":[0,1,0], "B":[2,0,5]}, columns=list('AB'))
>>> df.loc[df.A == 0, 'B'] = np.nan
>>> df
   A   B
0  0 NaN
1  1   0
2  0 NaN
>>> 

설명:

여기 문서 에서 설명했듯이 , .loc 주로 레이블 기반이지만 부울 배열과 함께 사용될 수도 있습니다 .

따라서 우리가 위에서하고있는 일은 df.loc[row_index, column_index]다음에 의해 적용 됩니다.

  • loc부울 배열을 마스크로 사용하여 팬더에게 변경하려는 행의 하위 집합을 알려주 는 사실을 악용row_index
  • 사실을 악용하는 것은 loc또한 라벨을 사용하여 열을 선택하는 기준으로 레이블입니다 'B'의를column_index

논리, 조건 또는 일련의 부울을 반환하는 모든 연산을 사용하여 부울 배열을 구성 할 수 있습니다. 위의 예에서 우리는 어떤 원하는 rows를 포함하는 0우리가 사용할 수에 대한, df.A == 0아래의 예를 불리언이 반환 시리즈에서 볼 수 있듯이을.

>>> df = pd.DataFrame({"A":[0,1,0], "B":[2,0,5]}, columns=list('AB'))
>>> df 
   A  B
0  0  2
1  1  0
2  0  5
>>> df.A == 0 
0     True
1    False
2     True
Name: A, dtype: bool
>>> 

그런 다음 위의 부울 배열을 사용하여 필요한 행을 선택하고 수정합니다.

>>> df.loc[df.A == 0, 'B'] = np.nan
>>> df
   A   B
0  0 NaN
1  1   0
2  0 NaN

자세한 내용은 여기 에서 고급 인덱싱 설명서를 확인 하십시오 .


11

속도를 크게 높이려면 NumPy의 where 함수를 사용하십시오.

설정

행이 100,000 인 행이 2 개인 DataFrame을 0으로 만듭니다.

df = pd.DataFrame(np.random.randint(0,3, (100000,2)), columns=list('ab'))

빠른 솔루션 numpy.where

df['b'] = np.where(df.a.values == 0, np.nan, df.b.values)

타이밍

%timeit df['b'] = np.where(df.a.values == 0, np.nan, df.b.values)
685 µs ± 6.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit df.loc[df['a'] == 0, 'b'] = np.nan
3.11 ms ± 17.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

Numpy where는 약 4 배 빠릅니다.


나는 이것에 대해 궁금해서 직접 테스트했으며 다른 매개 변수를 사용하면 차이가 훨씬 커졌습니다. Numpy는 0을 np.nan 대신 정수로 바꾸면 거의 10 배 빠릅니다. 여분의 시간이 걸리는 것이 궁금합니다.
Alexander

그것은 사용하는 것이 필요하다 .valuesnp.where(df.a.values == 0, np.nan, df.b.values)? np.where(df.a == 0, np.nan, df.b)작동하는 것 같 습니까?
hsl

4

여러 열을 바꾸려면 .values다음을 사용하여 numpy 배열로 변환하십시오 .

df.loc[df.A==0, ['B', 'C']] = df.loc[df.A==0, ['B', 'C']].values / 2
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.