IT TIP

Pandas의 다른 값을 기반으로 한 값 변경

itqueen 2020. 10. 13. 20:02
반응형

Pandas의 다른 값을 기반으로 한 값 변경


속도 향상을 위해 Stata 코드를 Python으로 재 프로그래밍하려고하는데 PANDAS의 지시를 받았습니다. 그러나 데이터 처리 방법에 대해 머리를 감싸는 데 어려움을 겪고 있습니다.

열 머리글 'ID'의 모든 값을 반복하고 싶다고 가정 해 보겠습니다. 해당 ID가 특정 번호와 일치하면 해당하는 두 개의 값인 FirstName과 LastName을 변경하고 싶습니다.

Stata에서는 다음과 같이 보입니다.

replace FirstName = "Matt" if ID==103
replace LastName =  "Jones" if ID==103

따라서 이것은 ID == 103의 값에 해당하는 FirstName의 모든 값을 Matt로 대체합니다.

PANDAS에서는 이런 식으로 시도하고 있습니다

df = read_csv("test.csv")
for i in df['ID']:
    if i ==103:
          ...

여기서 어디로 가야할지 모르겠습니다. 어떤 아이디어?


한 가지 옵션은 Python의 슬라이싱 및 인덱싱 기능을 사용하여 조건이 유지되는 위치를 논리적으로 평가하고 데이터를 덮어 쓰는 것입니다.

직접으로 데이터를로드 할 수 있습니다 가정 pandas을 가진 것은 pandas.read_csv다음 코드는 당신을 위해 도움이 될 수 있습니다.

import pandas
df = pandas.read_csv("test.csv")
df.loc[df.ID == 103, 'FirstName'] = "Matt"
df.loc[df.ID == 103, 'LastName'] = "Jones"

주석에서 언급했듯이 한 번에 두 열에 할당을 수행 할 수도 있습니다.

df.loc[df.ID == 103, ['FirstName', 'LastName']] = 'Matt', 'Jones'

덮어 쓰기 할당 작업에 pandas사용 하려면 버전 0.11 이상 이 필요 loc합니다.


이를 수행하는 또 다른 방법은 체인 할당이라고하는 것을 사용하는 것입니다. 이것의 동작은 덜 안정적이므로 최상의 솔루션으로 간주되지 않지만 ( 문서에서 명시 적으로 권장 되지 않음 ) 다음에 대해 아는 것이 유용합니다.

import pandas
df = pandas.read_csv("test.csv")
df['FirstName'][df.ID == 103] = "Matt"
df['LastName'][df.ID == 103] = "Jones"

를 사용할 수 있으며 map, dictonairy 또는 사용자 정의 함수의 값을 매핑 할 수 있습니다.

이것이 귀하의 df라고 가정하십시오.

    ID First_Name Last_Name
0  103          a         b
1  104          c         d

사전을 작성하십시오.

fnames = {103: "Matt", 104: "Mr"}
lnames = {103: "Jones", 104: "X"}

그리고지도 :

df['First_Name'] = df['ID'].map(fnames)
df['Last_Name'] = df['ID'].map(lnames)

결과는 다음과 같습니다.

    ID First_Name Last_Name
0  103       Matt     Jones
1  104         Mr         X

또는 사용자 정의 함수를 사용하십시오.

names = {103: ("Matt", "Jones"), 104: ("Mr", "X")}
df['First_Name'] = df['ID'].map(lambda x: names[x][0])

이 질문은 Kassies의 답변에 대한 부록을 제공 할 가치가있을만큼 자주 방문 할 수 있습니다. dict내장 클래스 하위 분류의 기본이 '실종'키에 대해 반환되도록 할 수 있습니다. 이 메커니즘은 판다에게 잘 작동합니다. 그러나 아래를 참조하십시오.

이러한 방식으로 주요 오류를 피할 수 있습니다.

>>> import pandas as pd
>>> data = { 'ID': [ 101, 201, 301, 401 ] }
>>> df = pd.DataFrame(data)
>>> class SurnameMap(dict):
...     def __missing__(self, key):
...         return ''
...     
>>> surnamemap = SurnameMap()
>>> surnamemap[101] = 'Mohanty'
>>> surnamemap[301] = 'Drake'
>>> df['Surname'] = df['ID'].apply(lambda x: surnamemap[x])
>>> df
    ID  Surname
0  101  Mohanty
1  201         
2  301    Drake
3  401         

다음과 같은 방법으로 더 간단하게 동일한 작업을 수행 할 수 있습니다. getdict 객체 메서드에 'default'인수를 사용하면 dict의 하위 클래스를 만들 필요가 없습니다.

>>> import pandas as pd
>>> data = { 'ID': [ 101, 201, 301, 401 ] }
>>> df = pd.DataFrame(data)
>>> surnamemap = {}
>>> surnamemap[101] = 'Mohanty'
>>> surnamemap[301] = 'Drake'
>>> df['Surname'] = df['ID'].apply(lambda x: surnamemap.get(x, ''))
>>> df
    ID  Surname
0  101  Mohanty
1  201         
2  301    Drake
3  401         

원래 질문은 특정 좁은 사용 사례를 다룹니다. 더 일반적인 답변이 필요한 사람들을 위해 다음과 같은 몇 가지 예가 있습니다.

다른 열의 데이터를 사용하여 새 열 만들기

아래 데이터 프레임이 주어지면 :

import pandas as pd
import numpy as np

df = pd.DataFrame([['dog', 'hound', 5],
                   ['cat', 'ragdoll', 1]],
                  columns=['animal', 'type', 'age'])

In[1]:
Out[1]:
  animal     type  age
----------------------
0    dog    hound    5
1    cat  ragdoll    1

Below we are adding a new description column as a concatenation of other columns by using the + operation which is overridden for series. Fancy string formatting, f-strings etc won't work here since the + applies to scalars and not 'primitive' values:

df['description'] = 'A ' + df.age.astype(str) + ' years old ' \
                    + df.type + ' ' + df.animal

In [2]: df
Out[2]:
  animal     type  age                description
-------------------------------------------------
0    dog    hound    5    A 5 years old hound dog
1    cat  ragdoll    1  A 1 years old ragdoll cat

We get 1 years for the cat (instead of 1 year) which we will be fixing below using conditionals.

Modifying an existing column with conditionals

Here we are replacing the original animal column with values from other columns, and using np.where to set a conditional substring based on the value of age:

# append 's' to 'age' if it's greater than 1
df.animal = df.animal + ", " + df.type + ", " + \
    df.age.astype(str) + " year" + np.where(df.age > 1, 's', '')

In [3]: df
Out[3]:
                 animal     type  age
-------------------------------------
0   dog, hound, 5 years    hound    5
1  cat, ragdoll, 1 year  ragdoll    1

Modifying multiple columns with conditionals

A more flexible approach is to call .apply() on an entire dataframe rather than on a single column:

def transform_row(r):
    r.animal = 'wild ' + r.type
    r.type = r.animal + ' creature'
    r.age = "{} year{}".format(r.age, r.age > 1 and 's' or '')
    return r

df.apply(transform_row, axis=1)

In[4]:
Out[4]:
         animal            type      age
----------------------------------------
0    wild hound    dog creature  5 years
1  wild ragdoll    cat creature   1 year

In the code above the transform_row(r) function takes a Series object representing a given row (indicated by axis=1, the default value of axis=0 will provide a Series object for each column). This simplifies processing since we can access the actual 'primitive' values in the row using the column names and have visibility of other cells in the given row/column.

참고URL : https://stackoverflow.com/questions/19226488/change-one-value-based-on-another-value-in-pandas

반응형