본문으로 바로가기
반응형

앞서서는 excel을 load하고 해당 정보를 읽는 방법에 대해서 얘기했습니다. 이번 포스팅에서는 pandas의 다양한 함수에 대해서 나열해 보고자 합니다.

이글은 Phtyon 3를 기반으로 작성되었습니다.

먼저 지난번에 로드했던 excel을 다시 로드합니다.

import pandas as pd
xls = pd.ExcelFile('yelp.xlsx')
df = xls.parse('yelp_data')
df.head()

Data Type의 변환

로드된 데이터의 column의 데이터 타입은 아래와 같습니다.

df.dtypes

때로는 string의 함수로 문자열을 편집하고 싶다면 그보다 먼저 type을 변경해야 합니다. stars (별점) 항목은 float64로 되어 있습니다. 한번 string으로 변경해 봅니다.

# astype(str) : string 타입으로 변경

# string으로 타입 변경
df['stars'] = df['stars'].astype(str)
print(df.dtypes)

stars의 type이 object로 변경되었습니다. -> string이 obejct이므로 object로 표현됩니다.

그럼 반대로 다시 숫자로의 변경은 아래와 같습니다.

# to_numeric(변경대상, 에러처리 방법)

# to_numeric() 숫자로 만들고 exception 나는건 무시함.
df['stars'] = pd.to_numeric(df['stars'], errors='coerce')
print(df.dtypes)

다시 float64로 변경됨을 확인할 수 있습니다. 'coerce'는 변경시 에러가 발생하면 무시하라는 표시 입니다.

# str.replace() - 문자열 치환

하나만 더해보겠습니다. string으로 변경한다면 이후에 string 함수를 이용하여 특정 값으로 치환할수도 있습니다.

#str.replace 문자열 변경
#take_out = df['take_out'].str.replace('True','TRUE') -> boolean 타입이므로 에러발생
take_out = df['take_out'].astype(str).str.replace('True','TRUE')
print(take_out)

astype(str) -> str.replace 함수를 통하여 문자열을 변경했습니다.

DataFrame의 join 연산

load한 excel에는 세개의 sheet가 존재 합니다. 기본 데이터를 저장하고 있는 sheet와 city 정보를 담고 있는 sheet, state를 담고있는 sheet로 구성되어 집니다. 먼저 raw data를 가진 sheet는 아래와 같습니다.

df.head()

'yelp_data' sheet의 내용

city_id와 state_id 컬럼이 있는데, 이는 다른 sheet에 실제 명칭들이 저장되어 있습니다.

먼저 cities sheet를 로드해 보면 아래와 가습니다.

df_cities = xls.parse('cities')
df_cities.head()

'cities' sheet의 내용

즉 이게 DB라고 생각한다면 sheet가 각 table이 되고 city_id와 state_id는 각 table을 연결하는 key값이 됩니다. table을 join하는것과 동일하게 아래와 같이 두개의 data_frame을 합칠 수 있습니다.

# pd.merge(left = 'data frame #1', right = 'data frame #2', how = 'join 형태', left_on='dataframe #1의 join key column', right_on='data frame #2의 join key column')

df = pd.merge(left=df, right=df_cities, how='inner', left_on='city_id', right_on='id')
df.head()

결과를 보면 오르쪽 끝에 'cities' 컬럼이 추가된것을 알수 있습니다.

how는 join의 형태로 기본적인 inner 조인을 사용합니다. 즉 join이 안되는 놈들은 row에서 사라지겠죠?

그럼 이제 state도 추가로 join해 보겠습니다.

df_states = xls.parse('states')
df_states.head()

state는 두곳밖에 없네요. 이제 같은 방식으로 cities가 조인되어 추가된 dataframe에 한번더 조인 합니다.

df = pd.merge(left=df, right=df_states, how='inner', left_on='state_id', right_on='id')
df.head()

조인은 잘 되었는데 'id'란 컬럼이 두개가 되었기 때문에 자동으로 'id_x', 'id_y'로 명명되어 보여집니다. 조인이 되어서 실제 city명과 state명이 표시 되므로 더이상 해당 컬럼은 필요 없으므로 column을 drop합니다.

# del dataframe['컬럼명'] - drop columns

del df['id_x']
del df['id_y']
df.head()

반응형

Slice - sql의 limit 역할

이번에 간단하게 ':'를 이용하여 데이터의 원하는 부분을 발췌해 봅니다. DB의 table이라면 limit의 역할을 대신 합니다.

df[100:200] # 100번째부터 199번째까지

df[100:] # 100번째 이후부터 끝까지
df[len(df)-1:] #마지막 row만 출력
df[-1:] # 마지막 row만 출력 (위와 동일)
df[-1:]['name'] #마지막 row의 이름을 출력

Boolean indexing - sql의 where절 역할

DB의 table이라면 join하는 방법과 limit로 결과를 짤라오는 방법을 언급했습니다. 그럼 where절 처럼 pandas에서 데이터 filtering를 하는 방법에 대해서 알아봅니다.

pitts = df['city'] == 'Pittsburgh' #filtering 조건을 boolean의 집합으로 생성
print(type(pitts)) # type은 pandas의 series임
print(pitts) #

city가 pittsburgh인것에 대한 boolen의 집합을 만듭니다. 

이 pitts의 type은 pandas의 Series이고, 600개의 각 라인별로 이게 참인지 거짓인지에 대한 결과가 저장됩니다.

그걸 아래와 같이 간단하게 dataframe에 넣으면 아래와 같이 filtering이 되서 나옵니다.

df[pitts]

600개 중에 193개만 출력되었습니다.

유사하게 가게 이름으로 filtering을 한다면 아래와 같이 할수 있습니다.

rest = df['name'] == 'The Dragon Chinese Cuisine'
df[rest]

이 Restaurants가 포장이 되는지만 뽑아 보려면 아래와 같이 질의 합니다.

df[rest]['take_out']

만역 복합적인 where 조건을 주려면 동일하게 여러개의 boolean index를 생성하면 됩니다. 카네기에 있는 Bars만 찾고 싶다고 한다면, 아래와 같이 질의할수 있습니다.

cat_0_bars = df['category_0'] == "Bars" #Category_0에서 bar를 찾음
cat_1_bars = df['category_1'] == "Bars" #Category_1에서 bar를 찾음
carnegie = df['city'] == "Carnegie" #도시에서 이름에서 Carnegie를 찾음
df[(cat_0_bars | cat_1_bars) & carnegie] # and/or 조건을 이용한 질의

요점은 boolean 값으로 표현할수 있으면 이를 index로 사용할 수 있다는점입니다.

별점이 4.0 이상인 가게만 뽑고 싶다면 아래와 같이 만들면 됩니다.

stars = df["stars"] >= 4.0
df[stars]

# isin([xxx,xxx,...]) - where절의 in 연산자 역할

sql의 in 연산자 처럼 특정 개수의 값은 전부 뽑아내고 싶을수 있습니다. 해당 조건을 모두 만들어 or 조건으로 붙여도 되지만 sql의 in 연산자 처럼 pandas 에서도 isin() 이라는 함수를 제공 합니다.

cat_0 = df['category_0'].isin(["Bars", "Restaurants"])
cat_1 = df['category_1'].isin(["Bars", "Restaurants"])
carnegie = df['city'] == "Carnegie"
df[(cat_0 | cat_1) & carnegie]

위와 같은 질의로 Carnegie 도시에 있는 Bars 와 Restaurants를 찾을 수 있습니다.

# str.contains(xxx) - where절의 like 연산자 역할

sql의 like 처럼 특정 문자열이 포함된것을 찾기 위한 조건은 str.contains를 이용합니다.

restaurants= df['category_0'].str.contains('Resta')
df[restaurants]

이는 sql의 like 검색에서 %xx%을 한것과 같습니다. 따라서 'Resta'에서 R을 뺀 'esta'로 검색을 해도 모든 Restaurants가 검색 됩니다.

# iloc - 특정 순번의 row를 뽑는다.

df.iloc[0] # 0번째 row를 출력
df[0:1] # 0번째 부터 1개의 row를 출력

두개의 결과는 같습니다. 다만 특정 row의 index를 알고 있고 해당 row 하나만 필요한 경우 위와 같이 iloc를 이용할수 도 있습니다.

반응형