Pandas를 사용하여 두 열 비교


104

이것을 시작점으로 사용 :

a = [['10', '1.2', '4.2'], ['15', '70', '0.03'], ['8', '5', '0']]
df = pd.DataFrame(a, columns=['one', 'two', 'three'])

Out[8]: 
  one  two three
0   10  1.2   4.2
1   15  70   0.03
2    8   5     0

if팬더 내 에서 진술 과 같은 것을 사용하고 싶습니다 .

if df['one'] >= df['two'] and df['one'] <= df['three']:
    df['que'] = df['one']

기본적으로 if문을 통해 각 행을 확인하고 새 열을 만듭니다.

문서는 사용하라고 말하지만 .all예가 없습니다 ...


if문이 다음과 같으면 값 은 False무엇입니까?
Alex Riley

3
@Merlin : 열에 숫자 데이터가있는 경우 문자열과 혼합하지 않는 것이 가장 좋습니다. 이렇게하면 열의 dtype이 object. 이렇게하면 임의의 Python 객체를 열에 저장할 수 있지만 숫자 계산 속도가 느려집니다. 따라서 열이 숫자 데이터를 저장하는 경우 숫자가 아닌 경우 NaN을 사용하는 것이 좋습니다.
unutbu 2014

1
정수를 문자열로 사용하고 비교하려고하면 이상하게 보입니다 : a = [['10', '1.2', '4.2'], ['15', '70', '0.03'], ['8', '5', '0']]. 이것은 "올바른"코드로 혼란스러운 결과를 생성합니다 : 입력이 정수일 경우 결과를 df['que'] = df['one'][(df['one'] >= df['two']) & (df['one'] <= df['three'])] 산출 10하는 반면 첫 번째 줄에 대해 산출 NaN합니다.
Primer 2014

답변:


147

np.where 사용할 수 있습니다 . 경우 cond부울 배열하고, A그리고 B다음, 배열 인

C = np.where(cond, A, B)

C가 A어디가 condTrue이고 B어디가 condFalse인지를 정의합니다.

import numpy as np
import pandas as pd

a = [['10', '1.2', '4.2'], ['15', '70', '0.03'], ['8', '5', '0']]
df = pd.DataFrame(a, columns=['one', 'two', 'three'])

df['que'] = np.where((df['one'] >= df['two']) & (df['one'] <= df['three'])
                     , df['one'], np.nan)

수확량

  one  two three  que
0  10  1.2   4.2   10
1  15   70  0.03  NaN
2   8    5     0  NaN

조건이 두 개 이상인 경우 대신 np.select 를 사용할 수 있습니다 . 예를 들어 다음 df['que']과 같을 df['two']df['one'] < df['two']

conditions = [
    (df['one'] >= df['two']) & (df['one'] <= df['three']), 
    df['one'] < df['two']]

choices = [df['one'], df['two']]

df['que'] = np.select(conditions, choices, default=np.nan)

수확량

  one  two three  que
0  10  1.2   4.2   10
1  15   70  0.03   70
2   8    5     0  NaN

df['one'] >= df['two']언제 df['one'] < df['two']가 False 라고 가정 할 수 있다면 조건과 선택을 다음과 같이 단순화 할 수 있습니다.

conditions = [
    df['one'] < df['two'],
    df['one'] <= df['three']]

choices = [df['two'], df['one']]

(가정은 NaN을 포함 df['one']하거나 df['two']포함하는 경우 사실이 아닐 수 있습니다 .)


참고

a = [['10', '1.2', '4.2'], ['15', '70', '0.03'], ['8', '5', '0']]
df = pd.DataFrame(a, columns=['one', 'two', 'three'])

문자열 값으로 DataFrame을 정의합니다. 숫자처럼 보이기 때문에 해당 문자열을 부동 소수점으로 변환하는 것이 더 나을 수 있습니다.

df2 = df.astype(float)

그러나 문자열은 문자별로 비교하고 부동 소수점은 숫자로 비교되므로 결과가 변경됩니다.

In [61]: '10' <= '4.2'
Out[61]: True

In [62]: 10 <= 4.2
Out[62]: False

73

.equals열 또는 전체 데이터 프레임에 사용할 수 있습니다 .

df['col1'].equals(df['col2'])

같으면 해당 문은 True, else 를 반환 합니다 False.


22
참고 : 이것은 전체 열을 다른 열과 만 비교합니다. 이것은 columsn 요소를 현명하게 비교하지 않습니다
guerda

1
한 열의 값이 항상 다른 열보다 "큼"또는 "작음"인지 확인하려면 어떻습니까?
rrlamichhane

28

apply () 사용하고 다음과 같이 할 수 있습니다.

df['que'] = df.apply(lambda x : x['one'] if x['one'] >= x['two'] and x['one'] <= x['three'] else "", axis=1)

또는 람다를 사용하지 않으려면

def que(x):
    if x['one'] >= x['two'] and x['one'] <= x['three']:
        return x['one']
    return ''
df['que'] = df.apply(que, axis=1)

2
pandas가 허용하는 벡터화 된 작업을 활용하지 않기 때문에 게시 된 다른 접근 방식보다 약간 느리다고 생각합니다.
Marius

@BobHaffner : 복잡한 if / then / else 문을 사용할 때 람다는 읽을 수 없습니다.
Merlin 2014

당신은 ELSEIF을 추가 할 수 있습니다 내가 람다 및 여러 조건에 당신과 함께 동의 @Merlin
밥 하프너

데이터 프레임 열을 전달할 수 있고 이름을 변경할 수 없도록 람다가 아닌 함수를 일반화하는 방법이 있습니까?
AZhao

@AZhao 다음과 같이 iloc으로 일반화 할 수 있습니다. df [ 'que'] = df.apply (lambda x : x.iloc [0] if x.iloc [0]> = x.iloc [1] and x.iloc [0 ] <= x.iloc [2] else "", axis = 1) 그게 무슨 뜻입니까? 명백하게. 문제 당신의 열의 순서
밥 하프너

9

한 가지 방법은 부울 계열을 사용하여 열을 인덱싱하는 것 df['one']입니다. 이렇게하면 새 열 수 있습니다 True항목과 동일한 행과 같은 값을 가질 df['one']False값은을 NaN.

Boolean 시리즈는 귀하의 if진술에 의해 제공됩니다 ( &대신 사용해야하지만 and).

>>> df['que'] = df['one'][(df['one'] >= df['two']) & (df['one'] <= df['three'])]
>>> df
    one two three   que
0   10  1.2 4.2      10
1   15  70  0.03    NaN
2   8   5   0       NaN

당신이 원하는 경우 NaN값을 다른 값으로 대체 할, 당신은 사용할 수있는 fillna새로운 열 방법을 que. 0여기에 빈 문자열 대신 사용 했습니다.

>>> df['que'] = df['que'].fillna(0)
>>> df
    one two three   que
0   10  1.2   4.2    10
1   15   70  0.03     0
2    8    5     0     0

4

각 개별 조건을 괄호로 묶은 다음 &연산자를 사용 하여 조건을 결합합니다.

df.loc[(df['one'] >= df['two']) & (df['one'] <= df['three']), 'que'] = df['one']

일치 ~를 반전시키기 위해 ( "not"연산자)를 사용하여 일치하지 않는 행을 채울 수 있습니다 .

df.loc[~ ((df['one'] >= df['two']) & (df['one'] <= df['three'])), 'que'] = ''

당신은 사용해야 &하고 ~대신 and하고 not있기 때문에 &~운영 작업 원소 별.

최종 결과 :

df
Out[8]: 
  one  two three que
0  10  1.2   4.2  10
1  15   70  0.03    
2   8    5     0  

1

사용하여 np.select다른 열에서 dataframe 및 출력 특정 선택에서 검사 할 여러 조건이있는 경우

conditions=[(condition1),(condition2)]
choices=["choice1","chocie2"]

df["new column"]=np.select=(condtion,choice,default=)

참고 : 조건 및 선택 항목이 일치하지 않아야합니다. 두 개의 다른 조건에 대해 동일한 선택이있는 경우 선택한 텍스트를 반복합니다.


0

OP의 직감에 가장 가까운 것은 인라인 if 문이라고 생각합니다.

df['que'] = (df['one'] if ((df['one'] >= df['two']) and (df['one'] <= df['three'])) 

귀하의 코드가 오류를 제공합니다df['que'] = (df['one'] if ((df['one'] >= df['two']) and (df['one'] <= df['three'])) ^ SyntaxError: unexpected EOF while parsing
vasili111
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.