Python 함수를 하나의 pandas 열에 적용하고 출력을 여러 열에 적용

Aug 20 2020

안녕하세요 커뮤니티,

나는 너무 많은 답변과 블로그를 읽었지만 내가 놓친 간단한 것이 무엇인지 알 수 없습니다!. 모든 조건을 정의하고 하나의 데이터 프레임 열에 적용하기 위해 '조건'기능을 사용하고 있습니다. 그리고 조건이 충족되면 'cat'및 'subcat'2 개의 새 데이터 프레임 열을 생성 / 업데이트해야합니다.

너희들이 여기서 나를 도울 수 있다면 큰 도움이 될 것입니다!

dict = {'remark':['NA','NA','Category1','Category2','Category3'],
        'desc':['Present','Present','NA','Present','NA']
} 

df = pd.DataFrame(dict) 

Dataframe은 다음과 같습니다.

          remark       desc
0         NA           Present      
1         NA           Present        
2         Category1    NA                   
3         Category2    Present                   
4         Category3    NA            

다음과 같이 조건을 정의하는 함수를 작성했습니다.

def conditions(s):

    if (s == 'Category1'):
        x = 'insufficient'
        y = 'resolution'
    elif (s=='Category2):
        x= 'insufficient'
        y= 'information'
    elif (s=='Category3):
        x= 'Duplicate'
        y= 'ID repeated'
    else:
        x= 'NA'
        y= 'NA'
    
    return (x,y)

데이터 프레임 열에서 위의 기능을 실행하는 데는 여러 가지 아이디어가 있지만 운이 없습니다.

df[['cat','subcat']] = df['remark'].apply(lambda x: pd.Series([conditions(df)[0],conditions(df)[1]]))

내 예상 데이터 프레임은 다음과 같아야합니다.

          remark       desc        cat           subcat
0         NA           Present     NA            NA      
1         NA           Present     NA            NA
2         Category1    NA          insufficient  resolution         
3         Category2    Present     insufficient  information              
4         Category3    NA          Duplicate     ID repeated

많은 감사합니다.

답변

2 sammywemmy Aug 20 2020 at 04:10

이 문제를 해결하는 한 가지 방법은 목록 이해입니다.

df[['cat', 'subcat']] = [("insufficient", "resolution")  if word == "Category1" else 
                         ("insufficient", "information") if word == "Category2" else
                         ("Duplicate", "ID repeated")    if word == "Category3" else 
                         ("NA", "NA")
                         for word in df.remark]

  remark      desc               cat         subcat
0   NA        Present          NA              NA
1   NA        Present          NA              NA
2   Category1   NA          insufficient    resolution
3   Category2   Present     insufficient    information
4   Category3   NA          Duplicate       ID repeated

@ dm2의 대답은 함수를 사용하는 방법을 보여줍니다. 첫 번째 apply(conditions)는 튜플을 포함하는 시리즈를 생성하고, 두 번째는 apply개별 열을 생성하여 cat및에 할당 할 수있는 데이터 프레임을 형성합니다 subcat.

내가 목록 이해를 제안하는 이유는 Strings를 다루고 있고 Pandas에서는 바닐라 파이썬을 통해 문자열로 작업하는 것이 더 빠르기 때문입니다. 또한 목록 이해를 사용하면 처리가 한 번 완료되므로 조건 함수를 적용한 다음을 호출 할 필요가 없습니다 pd.Series. 그것은 당신에게 더 빠른 속도를 제공합니다. 테스트는 이것을 주장하거나 반박 할 것입니다.

2 dm2 Aug 20 2020 at 04:12

다음과 같이 할 수 있습니다.

 df[['cat','subcat']] = df['remark'].apply(conditions).apply(pd.Series)

산출:

  remark      desc               cat         subcat
0   NA        Present          NA              NA
1   NA        Present          NA              NA
2   Category1   NA          insufficient    resolution
3   Category2   Present     insufficient    information
4   Category3   NA          Duplicate       ID repeated

편집 : 이것은 이미 가지고있는 기능을 적용하는 더 간단한 방법 일 수 있지만 거대한 DataFrame이있는 경우 더 빠른 코드를 위해 목록 이해를 사용하여 @sammywemmy의 답변을 확인하십시오.

1 Quentin Aug 20 2020 at 04:13

dataframe람다 변수 ( x) 를 전달해야하는 곳에 전체 를 전달합니다 .

df[['cat','subcat']] = df['remark'].apply(lambda x: pd.Series([*conditions(x)]))

*iterables에서는 unpack출력을 추출하기 위해 동일한 함수를 두 번 호출 할 필요가 없습니다. 아마도 컴파일러가 이것을 해결하지만 그렇게 생각하지 않습니다 ...

RichieV Aug 20 2020 at 04:11

series.replace매핑 사전과 함께 사용할 수 있습니다.

df['cat'] = df.remark.replace({'Category1': 'insufficient',
    'Category2': 'insufficient', 'Category3': 'Duplicate'})
df['subcat'] = df.remark.replace({'Category1': 'resolution',
    'Category2': 'information', 'Category3': 'ID repeated'})

print(df)
      remark     desc           cat       subcat
0         NA  Present            NA           NA
1         NA  Present            NA           NA
2  Category1       NA  insufficient   resolution
3  Category2  Present  insufficient  information
4  Category3       NA     Duplicate  ID repeated