40 분 소요



라이브러리 불러오기

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline 

import math



Series

  • pandas의 기본 객체 중 하나
  • numpy의 ndarray를 기반으로 인덱싱을 기능을 추가하여 1차원 배열을 나타냄
  • index를 지정하지 않을 시, 기본적으로 ndarray와 같이 0-based 인덱스 생성, 지정할 경우 명시적으로 지정된 index를 사용
  • 같은 타입의 0개 이상의 데이터를 가질 수 있음
pd.Series([1, 2, 3])

image



pd.Series(['a', 'b', 'c'])

image

pd.Series(np.arange(200))
0        0
1        1
2        2
3        3
4        4
      ... 
195    195
196    196
197    197
198    198
199    199
Length: 200, dtype: int32



data와 index 함께 명시하기

pd.Series([1,2,3], ['a','m','k']) # 첫번째는 data, 두번째는 인덱스 값
a    1
m    2
k    3
dtype: int64



data, index, data type 함께 명시하기(dtype)

s6 =pd.Series(np.arange(5), np.arange(100, 105), dtype=np.int16)
s6
100    0
101    1
102    2
103    3
104    4
dtype: int16



인덱스 활용하기

s = pd.Series([1, 1, 2, 1, 2, 2, 2, 1, 1, 3, 3, 4, 5, 5, 7, np.NaN]) #np.Nan는 결측치
s
0     1.0
1     1.0
2     2.0
3     1.0
4     2.0
5     2.0
6     2.0
7     1.0
8     1.0
9     3.0
10    3.0
11    4.0
12    5.0
13    5.0
14    7.0
15    NaN
dtype: float64



index 값

s6.index 
Int64Index([100, 101, 102, 103, 104], dtype='int64')



values 값

s6.values 
array([0, 1, 2, 3, 4], dtype=int16)



Series 함수


size

  • 개수 반환
len(s)
16
s.size
16



shape

  • 튜플형태로 shape반환
s.shape
(16,)



unique

  • 유일한 값만 ndarry로 반환
s.unique() #unique는 중복x 한개의 문자만 가져옴
array([ 1.,  2.,  3.,  4.,  5.,  7., nan])



count

  • NaN을 제외한 개수를 반환
s.count() #실제 값만 카운트해서 반환
5



mean

  • NaN을 제외한 평균
s.mean()
2.6666666



value_counts

  • NaN을 제외하고 각 값들의 빈도를 반환
  • 데이터의 개수 빈도를 알고 싶을때 가장 많이 쓰는 함수 중 하나
  • index를 활용하여 멀티플한 값에 접근
  • 갖고오고 싶은 인덱스를 리스트 형식으로 해서 반환
s.value_counts() 
1.0    5
2.0    4
5.0    2
3.0    2
7.0    1
4.0    1
dtype: int64



  • head : 상위 n개 출력 기본 5개
s.head(n=7) #기본적으로 상위 5개
0    1.0
1    1.0
2    2.0
3    1.0
4    2.0
5    2.0
6    2.0
dtype: float64



tail()

  • tail : 하위 n개 출력 기본 5개
s.tail() #기본적으로 하위 5개
11    4.0
12    5.0
13    5.0
14    7.0
15    NaN
dtype: float64



산술연산

  • Series의 경우에도 스칼라와의 연산은 각 원소별로 스칼라와의 연산이 적용
  • Series와의 연산은 각 인덱스에 맞는 값끼리 연산이 적용
  • 이때, 인덱스의 pair가 맞지 않으면, 결과는 NaN
s = pd.Series(np.arange(10), np.arange(10)+1)
s
1     0
2     1
3     2
4     3
5     4
6     5
7     6
8     7
9     8
10    9
dtype: int32



조건식

s[s>5] # True인 것만 필터링해서 가져옴 
7     6
8     7
9     8
10    9
dtype: int32
s[s % 2 == 0]
1    0
3    2
5    4
7    6
9    8
dtype: int32
s[s.index > 5] # s의 index를 기준으로 반환
6     5
7     6
8     7
9     8
10    9
dtype: int32
s[(s > 5) & (s < 8)] #괄호를 반드시 묶어줘야 한다.
7    6
8    7
dtype: int32
(s >= 7).sum() # boolean array의 참 개수를 구하는 것 
3
s = pd.Series(np.arange(100, 105), ['a', 'b', 'c', 'd', 'e'])

s
a    100
b    101
c    102
d    103
e    104
dtype: int32
s['a'] = 200 # 이미 있는 건 갱신 

s
a    200
b    101
c    102
d    103
e    104
dtype: int32
s['k'] = 300 # 없는 건 추가

s
a    200
b    101
c    102
d    103
e    104
k    300
dtype: int64



drop()

  • drop은 s 자체에는 지워지지 않는다.
  • 기본 inplace 값은 false. true이면 그 자체에 반환
  • p.s. del은 원본에 바로 삭제
s.drop('k', inplace=True)  

s
a    200
b    101
c    102
d    103
e    104
dtype: int64



update

s[['a', 'b']] = [300, 900] # 한꺼번에 update 가능

s
a    300
b    900
c    102
d    103
e    104
dtype: int64



Slicing

  • 리스트, ndarray와 동일하게 적용
s1 = pd.Series(np.arange(100, 105))

s1
0    100
1    101
2    102
3    103
4    104
dtype: int32
s1[1:3]
1    101
2    102
dtype: int32
s2 = pd.Series(np.arange(100, 105), ['a', 'c', 'b', 'd', 'e'])

s2
a    100
c    101
b    102
d    103
e    104
dtype: int32
s2['c':'d'] # 문자열로 인덱싱 할때는 마지막 포함한다.
c    101
b    102
d    103
dtype: int32



concat

pd.concat(objs,  # Series, DataFrame, Panel object

axis=0,  # 0: 위+아래로 합치기, 1: 왼쪽+오른쪽으로 합치기

join='outer', # 'outer': 합집합(union), 'inner': 교집합(intersection)

join_axes=None, # axis=1 일 경우 특정 DataFrame의 index를 그대로 이용하려면 입력 (deprecated, 더이상 지원하지 않음)

ignore_index=False,  # False: 기존 index 유지, True: 기존 index 무시

keys=None, # 계층적 index 사용하려면 keys 튜플 입력
levels=None,

names=None, # index의 이름 부여하려면 names 튜플 입력

verify_integrity=False, # True: index 중복 확인

copy=True) # 복사



axis = 0

  • 위 + 아래로 DataFrame 합치기(rbind)



axis = 1

  • 왼쪽 + 오른쪽으로 DataFrame 합치기(cbind)



join = ‘outer’

  • 합집합(union)으로 DataFrame 합치기



join = ‘inner’

  • 교집합(intersection)으로 DataFrame 합치기



join_axes

  • axis=1일 경우 특정 DataFrame의 index를 그대로 이용하고자 할 경우



ignore_index

  • 기존 index를 무시하고 싶을 때



keys

  • 계층적 index (hierarchical index) 만들기



names

  • index에 이름 부여하기



verify_integrity

  • index 중복 여부 점검



merge

pd.merge(left, right, # merge할 DataFrame 객체 이름

how='inner', # left, rigth, inner (default), outer

on=None, # merge의 기준이 되는 Key 변수

left_on=None, # 왼쪽 DataFrame의 변수를 Key로 사용

right_on=None, # 오른쪽 DataFrame의 변수를 Key로 사용

left_index=False, # 만약 True 라면, 왼쪽 DataFrame의 index를 merge 

Key로 사용

right_index=False, # 만약 True 라면, 오른쪽 DataFrame의 index를 merge Key로 사용

sort=True, # merge 된 후의 DataFrame을 join Key 기준으로 정렬

suffixes=('_x', '_y'), # 중복되는 변수 이름에 대해 접두사 부여 (defaults to '_x', '_y'

copy=True, # merge할 DataFrame을 복사

indicator=False) # 병합된 이후의 DataFrame에 left_only, right_only, both 등의 출처를 알 수 있는 부가 정보 변수 추가



DataFrame

  • Series가 1차원이라면 DataFrame은 2차원으로 확대된 버젼
  • Excel spreadsheet이라고 생각하면 이해하기 쉬움
  • 2차원이기 때문에 인덱스가 row, column로 구성됨
  • row는 각 개별 데이터를, column은 개별 속성을 의미
  • Data Analysis, Machine Learning에서 data 변형을 위해 가장 많이 사용



DataFrame 생성하기

  • 일반적으로 분석을 위한 데이터는 다른 데이터 소스(database, 외부 파일)을 통해 dataframe을 생성
  • 여기서는 실습을 통해, dummy 데이터를 생성하는 방법을 다룰 예정



dictionary로 부터 생성하기

  • dict의 key -> column
data = {'a' : 100, 'b' : 200, 'c' : 300}

pd.DataFrame(data, index=['x', 'y', 'z'])
a b c
x 100 200 300
y 100 200 300
z 100 200 300
data = {'a' : [1, 2, 3], 'b' : [4, 5, 6], 'c' : [10, 11, 12]}

pd.DataFrame(data, index=[0, 1, 2])
a b c
0 1 4 10
1 2 5 11
2 3 6 12



Series로 부터 생성하기

  • 각 Series의 인덱스 -> column
a = pd.Series([100, 200, 300], ['a', 'b', 'd'])

b = pd.Series([101, 201, 301], ['a', 'b', 'k'])

c = pd.Series([110, 210, 310], ['a', 'b', 'c'])



pd.DataFrame([a, b, c], index=[100, 101, 102])
a b d k c
100 100.0 200.0 300.0 NaN NaN
101 101.0 201.0 NaN 301.0 NaN
102 110.0 210.0 NaN NaN 310.0
# data 출처: https://www.kaggle.com/hesh97/titanicdataset-traincsv/data

train_data = pd.read_csv('F:/data/titanic/train.csv') 

# ./ : 현재 폴더를 의미 # sep="," : 각각 데이터를 ,로 구분



head, tail 함수

  • 데이터 전체가 아닌, 일부(처음부터, 혹은 마지막부터)를 간단히 보기 위한 함수
train_data.head(n=3)
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C
2 3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S
train_data.tail(n=10)
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
881 882 0 3 Markun, Mr. Johann male 33.0 0 0 349257 7.8958 NaN S
882 883 0 3 Dahlberg, Miss. Gerda Ulrika female 22.0 0 0 7552 10.5167 NaN S
883 884 0 2 Banfield, Mr. Frederick James male 28.0 0 0 C.A./SOTON 34068 10.5000 NaN S
884 885 0 3 Sutehall, Mr. Henry Jr male 25.0 0 0 SOTON/OQ 392076 7.0500 NaN S
885 886 0 3 Rice, Mrs. William (Margaret Norton) female 39.0 0 5 382652 29.1250 NaN Q
886 887 0 2 Montvila, Rev. Juozas male 27.0 0 0 211536 13.0000 NaN S
887 888 1 1 Graham, Miss. Margaret Edith female 19.0 0 0 112053 30.0000 B42 S
888 889 0 3 Johnston, Miss. Catherine Helen "Carrie" female NaN 1 2 W./C. 6607 23.4500 NaN S
889 890 1 1 Behr, Mr. Karl Howell male 26.0 0 0 111369 30.0000 C148 C
890 891 0 3 Dooley, Mr. Patrick male 32.0 0 0 370376 7.7500 NaN Q



변수 이름(column name, header)이 없는 파일 불러올 때 이름 부여하기

: names=[‘X1’,’X2’, ..], header=None

pd.read_csv('e:/data/text_without_column_name.txt', sep='|',

names=['ID','A','B','C','D'], header=None, index_col='ID')

#names=['ID', 'A', 'B', 'C', 'D'] 와 같이 칼럼 이름을 부여해줍니다.

# header=None 은 칼럼 이름이 없다는 뜻이며, 

# 만약 1번째 행이 칼럼 이름이라면 header=0 으로 지정해주면 됩니다.
A B C D
ID
C1 1 2 3 4
C2 5 6 7 8
C3 1 3 5 7



유니코드 디코드 에러날때

  • cp949써보기 (encoding=’cp949’)

  • 그래도 안되면

    • encoding=’latin’

특정 줄은 제외하고 불러오기: skiprows = [x, x]

pd.read_csv('e:/data/text_without_column_name.txt', sep='|',

names=['ID','A','B','C','D'], header=None, index_col='ID',

skiprows=[1])
A B C D
ID
C1 1 2 3 4
C3 1 3 5 7



nrows = n

  • n 개의 행만 불러오기
  • csv 파일의 위에서 부터 3개의 행(rows) 만 DataFrame으로 불러오기
csv_3 = pd.read_csv('f:/data/test_csv_file.csv', nrows=3); csv_3
ID LAST_NAME AGE
0 1 KIM 30
1 2 CHOI 25
2 3 LEE 41



사용자 정의 결측값 기호 (custom missing value symbols)

df = pd.read_csv('e:/data/test_text_file.txt', sep='|', 

na_values = ['?', '??', 'N/A', 'NA', 'nan', 'NaN', '-nan', '-NaN', 'null'])
df
ID A B C D
0 C1 1 2 3 4
1 C2 5 6 7 8
2 C3 1 3 5 7

pandas DataFrame 만들기

df_1 = pd.DataFrame(data=np.arange(12).reshape(3, 4),

index=['r0', 'r1', 'r2'], # Will default to np.arange(n) if no indexing

columns=['c0', 'c1', 'c2', 'c3'],

dtype='int', # Data type to force, otherwise infer

copy=False) # Copy data from inputs

df_1
c0 c1 c2 c3
r0 0 1 2 3
r1 4 5 6 7
r2 8 9 10 11
df_1.T
r0 r1 r2
c0 0 4 8
c1 1 5 9
c2 2 6 10
c3 3 7 11



axes()

# axes : 행과 열 이름을 리스트로 변환 

df_1.axes
[Index(['r0', 'r1', 'r2'], dtype='object'),
 Index(['c0', 'c1', 'c2', 'c3'], dtype='object')]



dtypes(), shape(), size(), values()

# dtypes : 데이터 형태 반환

# shape : 행과 열의 개수(차원)을 튜플로 반환

# size : NDFrame의 원소의 개수를 반환

# values : NDFrame의 원소를 numpy 형태로 반환




reindex()

# index 재설정하기 

new_idx = ['r0', 'r1', 'r2', 'r5', 'r6']



# reindex 과정에서 생긴 결측값 채우기 (fill in missing values) : fill_value

df_1.reindex(new_idx, fill_value=0)
c0 c1 c2 c3
r0 0 1 2 3
r1 4 5 6 7
r2 8 9 10 11
r5 0 0 0 0
r6 0 0 0 0



시계열 데이터

  • DataFrame의 index만들 때, pd.date_range(date,periods, freq)
date_idx=pd.date_range('2021-08-05', periods=5, freq='D')
date_idx
DatetimeIndex(['2021-08-05', '2021-08-06', '2021-08-07', '2021-08-08',
               '2021-08-09'],
              dtype='datetime64[ns]', freq='D')



dataframe 데이터 파악하기

  • shape 속성 (row, column)

  • describe 함수 - 숫자형 데이터의 통계치 계산

  • info 함수 - 데이터 타입, 각 아이템의 개수 등 출력

train_data.shape # (891, 12) = 891개의 데이터가 있고 12개의 속성이 있다.
(891, 12)
train_data.describe()
PassengerId Survived Pclass Age SibSp Parch Fare
count 891.000000 891.000000 891.000000 714.000000 891.000000 891.000000 891.000000
mean 446.000000 0.383838 2.308642 29.699118 0.523008 0.381594 32.204208
std 257.353842 0.486592 0.836071 14.526497 1.102743 0.806057 49.693429
min 1.000000 0.000000 1.000000 0.420000 0.000000 0.000000 0.000000
25% 223.500000 0.000000 2.000000 20.125000 0.000000 0.000000 7.910400
50% 446.000000 0.000000 3.000000 28.000000 0.000000 0.000000 14.454200
75% 668.500000 1.000000 3.000000 38.000000 1.000000 0.000000 31.000000
max 891.000000 1.000000 3.000000 80.000000 8.000000 6.000000 512.329200



info함수로 각 변수의 데이터 타입 확인

  • 타입 변경은 astype함수를 사용
train_data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):
 #   Column       Non-Null Count  Dtype  
---  ------       --------------  -----  
 0   PassengerId  891 non-null    int64  
 1   Survived     891 non-null    int64  
 2   Pclass       891 non-null    int64  
 3   Name         891 non-null    object 
 4   Sex          891 non-null    object 
 5   Age          714 non-null    float64
 6   SibSp        891 non-null    int64  
 7   Parch        891 non-null    int64  
 8   Ticket       891 non-null    object 
 9   Fare         891 non-null    float64
 10  Cabin        204 non-null    object 
 11  Embarked     889 non-null    object 
dtypes: float64(2), int64(5), object(5)
memory usage: 83.7+ KB



인덱스(index)

  • index 속성

  • 각 아이템을 특정할 수 있는 고유의 값을 저장

  • 복잡한 데이터의 경우, 멀티 인덱스로 표현 가능

train_data.index
RangeIndex(start=0, stop=891, step=1)



컬럼(column)

  • columns 속성

  • 각각의 특성(feature)을 나타냄

  • 복잡한 데이터의 경우, 멀티 컬럼으로 표현 가능

train_data.columns
Index(['PassengerId', 'Survived', 'Pclass', 'Name', 'Sex', 'Age', 'SibSp',
       'Parch', 'Ticket', 'Fare', 'Cabin', 'Embarked'],
      dtype='object')



read_csv 함수 파라미터

  • sep - 각 데이터 값을 구별하기 위한 구분자(separator) 설정

  • header - header를 무시할 경우, None 설정

  • index_col - index로 사용할 column 설정

  • usecols - 실제로 dataframe에 로딩할 columns만 설정

train_data1 = pd.read_csv('E:\kaggle/titanic/train.csv', index_col='PassengerId', usecols=['PassengerId', 'Survived', 'Pclass', 'Name']) 

# index_col = passengerId가 인덱스로 존재 # usecols = 필요한 컴럼만 가져온다.

# index_col = 파일 불러올때 index 지정해주기

train_data1
Survived Pclass Name
PassengerId
1 0 3 Braund, Mr. Owen Harris
2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th...
3 1 3 Heikkinen, Miss. Laina
4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel)
5 0 3 Allen, Mr. William Henry
... ... ... ...
887 0 2 Montvila, Rev. Juozas
888 1 1 Graham, Miss. Margaret Edith
889 0 3 Johnston, Miss. Catherine Helen "Carrie"
890 1 1 Behr, Mr. Karl Howell
891 0 3 Dooley, Mr. Patrick

891 rows × 3 columns



하나의 컬럼 선택하기

train_data['Survived'] # 특정 컬럼만 series로 가져온다.  
0      0
1      1
2      1
3      1
4      0
      ..
886    0
887    1
888    0
889    1
890    0
Name: Survived, Length: 891, dtype: int64



복수의 컬럼 선택하기

train_data[['Survived', 'Name', 'Age', 'Embarked']]
Survived Name Age Embarked
0 0 Braund, Mr. Owen Harris 22.0 S
1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... 38.0 C
2 1 Heikkinen, Miss. Laina 26.0 S
3 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) 35.0 S
4 0 Allen, Mr. William Henry 35.0 S
... ... ... ... ...
886 0 Montvila, Rev. Juozas 27.0 S
887 1 Graham, Miss. Margaret Edith 19.0 S
888 0 Johnston, Miss. Catherine Helen "Carrie" NaN S
889 1 Behr, Mr. Karl Howell 26.0 C
890 0 Dooley, Mr. Patrick 32.0 Q

891 rows × 4 columns

train_data[['Survived']] #이건 데이터 프레임으로 가져온다.
Survived
0 0
1 1
2 1
3 1
4 0
... ...
886 0
887 1
888 0
889 1
890 0

891 rows × 1 columns



dataframe slicing

  • dataframe의 경우 기본적으로 [] 연산자가 column 선택에 사용

  • 하지만, slicing은 row 레벨로 지원

train_data[7:10] # 슬라이싱은 row로 적용 # 슬라이싱만 예외
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
7 8 0 3 Palsson, Master. Gosta Leonard male 2.0 3 1 349909 21.0750 NaN S
8 9 1 3 Johnson, Mrs. Oscar W (Elisabeth Vilhelmina Berg) female 27.0 0 2 347742 11.1333 NaN S
9 10 1 2 Nasser, Mrs. Nicholas (Adele Achem) female 14.0 1 0 237736 30.0708 NaN C



row 선택하기

  • Seires의 경우 []로 row 선택이 가능하나, DataFrame의 경우는 기본적으로 column을 선택하도록 설계

  • .loc, .iloc로 row 선택 가능

    • loc - 인덱스 자체를 사용

    • iloc - 0 based index로 사용

    • 이 두 함수는 ,를 사용하여 column 선택도 가능

train_data.index = np.arange(100, 991)
train_data.loc[986] # 존재하는 index를 가져옴 
PassengerId                      887
Survived                           0
Pclass                             2
Name           Montvila, Rev. Juozas
Sex                             male
Age                               27
SibSp                              0
Parch                              0
Ticket                        211536
Fare                              13
Cabin                            NaN
Embarked                           S
Name: 986, dtype: object
train_data.loc[[986, 100, 110, 990]]
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
986 887 0 2 Montvila, Rev. Juozas male 27.0 0 0 211536 13.00 NaN S
100 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.25 NaN S
110 11 1 3 Sandstrom, Miss. Marguerite Rut female 4.0 1 1 PP 9549 16.70 G6 S
990 891 0 3 Dooley, Mr. Patrick male 32.0 0 0 370376 7.75 NaN Q



train_data.iloc[[0, 100, 200, 2]] 

# index 관계없이 0부터 시작하는 index base를 가져옴
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
100 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S
200 101 0 3 Petranec, Miss. Matilda female 28.0 0 0 349245 7.8958 NaN S
300 201 0 3 Vande Walle, Mr. Nestor Cyriel male 28.0 0 0 345770 9.5000 NaN S
102 3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S



row, column 동시에 선택하기

  • loc, iloc 속성을 이용할 때, 콤마를 이용하여 둘 다 명시 가능
train_data.loc[[986, 100, 110, 990], ['Survived', 'Name', 'Sex', 'Age']]

# loc = location
Survived Name Sex Age
986 0 Montvila, Rev. Juozas male 27.0
100 0 Braund, Mr. Owen Harris male 22.0
110 1 Sandstrom, Miss. Marguerite Rut female 4.0
990 0 Dooley, Mr. Patrick male 32.0



train_data.iloc[[101, 100, 200, 102], [1, 4, 5]] # columns 역시 0베이스부터 시작
Survived Sex Age
201 0 male NaN
200 0 female 28.0
300 0 male 28.0
202 0 male 21.0



train_data = pd.read_csv('E:\kaggle/titanic/train.csv')

boolean selection으로 row 선택하기

  • numpy에서와 동일한 방식으로 해당 조건에 맞는 row만 선택

30대이면서 1등석에 탄 사람 선택하기

class_ = train_data['Pclass'] == 1

age_ = (train_data['Age'] >= 30) & (train_data['Age'] < 40)



train_data[class_ & age_]
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C
3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S
61 62 1 1 Icard, Miss. Amelie female 38.0 0 0 113572 80.0000 B28 NaN
137 138 0 1 Futrelle, Mr. Jacques Heath male 37.0 1 0 113803 53.1000 C123 S
215 216 1 1 Newell, Miss. Madeleine female 31.0 1 0 35273 113.2750 D36 C
218 219 1 1 Bazzani, Miss. Albina female 32.0 0 0 11813 76.2917 D15 C
224 225 1 1 Hoyt, Mr. Frederick Maxfield male 38.0 1 0 19943 90.0000 C93 S
230 231 1 1 Harris, Mrs. Henry Birkhardt (Irene Wallach) female 35.0 1 0 36973 83.4750 C83 S
248 249 1 1 Beckwith, Mr. Richard Leonard male 37.0 1 1 11751 52.5542 D35 S
257 258 1 1 Cherry, Miss. Gladys female 30.0 0 0 110152 86.5000 B77 S
258 259 1 1 Ward, Miss. Anna female 35.0 0 0 PC 17755 512.3292 NaN C
269 270 1 1 Bissette, Miss. Amelia female 35.0 0 0 PC 17760 135.6333 C99 S
273 274 0 1 Natsch, Mr. Charles H male 37.0 0 1 PC 17596 29.7000 C118 C
309 310 1 1 Francatelli, Miss. Laura Mabel female 30.0 0 0 PC 17485 56.9292 E36 C
318 319 1 1 Wick, Miss. Mary Natalie female 31.0 0 2 36928 164.8667 C7 S
325 326 1 1 Young, Miss. Marie Grice female 36.0 0 0 PC 17760 135.6333 C32 C
332 333 0 1 Graham, Mr. George Edward male 38.0 0 1 PC 17582 153.4625 C91 S
383 384 1 1 Holverson, Mrs. Alexander Oskar (Mary Aline To... female 35.0 1 0 113789 52.0000 NaN S
390 391 1 1 Carter, Mr. William Ernest male 36.0 1 2 113760 120.0000 B96 B98 S
412 413 1 1 Minahan, Miss. Daisy E female 33.0 1 0 19928 90.0000 C78 Q
447 448 1 1 Seward, Mr. Frederic Kimber male 34.0 0 0 113794 26.5500 NaN S
452 453 0 1 Foreman, Mr. Benjamin Laventall male 30.0 0 0 113051 27.7500 C111 C
486 487 1 1 Hoyt, Mrs. Frederick Maxfield (Jane Anne Forby) female 35.0 1 0 19943 90.0000 C93 S
512 513 1 1 McGough, Mr. James Robert male 36.0 0 0 PC 17473 26.2875 E25 S
520 521 1 1 Perreault, Miss. Anne female 30.0 0 0 12749 93.5000 B73 S
537 538 1 1 LeRoy, Miss. Bertha female 30.0 0 0 PC 17761 106.4250 NaN C
540 541 1 1 Crosby, Miss. Harriet R female 36.0 0 2 WE/P 5735 71.0000 B22 S
558 559 1 1 Taussig, Mrs. Emil (Tillie Mandelbaum) female 39.0 1 1 110413 79.6500 E67 S
572 573 1 1 Flynn, Mr. John Irwin ("Irving") male 36.0 0 0 PC 17474 26.3875 E25 S
577 578 1 1 Silvey, Mrs. William Baird (Alice Munger) female 39.0 1 0 13507 55.9000 E44 S
581 582 1 1 Thayer, Mrs. John Borland (Marian Longstreth M... female 39.0 1 1 17421 110.8833 C68 C
583 584 0 1 Ross, Mr. John Hugo male 36.0 0 0 13049 40.1250 A10 C
604 605 1 1 Homer, Mr. Harry ("Mr E Haven") male 35.0 0 0 111426 26.5500 NaN C
632 633 1 1 Stahelin-Maeglin, Dr. Max male 32.0 0 0 13214 30.5000 B50 C
671 672 0 1 Davidson, Mr. Thornton male 31.0 1 0 F.C. 12750 52.0000 B71 S
679 680 1 1 Cardeza, Mr. Thomas Drake Martinez male 36.0 0 1 PC 17755 512.3292 B51 B53 B55 C
690 691 1 1 Dick, Mr. Albert Adrian male 31.0 1 0 17474 57.0000 B20 S
701 702 1 1 Silverthorne, Mr. Spencer Victor male 35.0 0 0 PC 17475 26.2875 E24 S
716 717 1 1 Endres, Miss. Caroline Louise female 38.0 0 0 PC 17757 227.5250 C45 C
737 738 1 1 Lesurer, Mr. Gustave J male 35.0 0 0 PC 17755 512.3292 B101 C
741 742 0 1 Cavendish, Mr. Tyrell William male 36.0 1 0 19877 78.8500 C46 S
759 760 1 1 Rothes, the Countess. of (Lucy Noel Martha Dye... female 33.0 0 0 110152 86.5000 B77 S
763 764 1 1 Carter, Mrs. William Ernest (Lucile Polk) female 36.0 1 2 113760 120.0000 B96 B98 S
806 807 0 1 Andrews, Mr. Thomas Jr male 39.0 0 0 112050 0.0000 A36 S
809 810 1 1 Chambers, Mrs. Norman Campbell (Bertha Griggs) female 33.0 1 0 113806 53.1000 E8 S
822 823 0 1 Reuchlin, Jonkheer. John George male 38.0 0 0 19972 0.0000 NaN S
835 836 1 1 Compton, Miss. Sara Rebecca female 39.0 1 1 PC 17756 83.1583 E49 C
842 843 1 1 Serepeca, Miss. Augusta female 30.0 0 0 113798 31.0000 NaN C
867 868 0 1 Roebling, Mr. Washington Augustus II male 31.0 0 0 PC 17590 50.4958 A24 S
872 873 0 1 Carlsson, Mr. Frans Olof male 33.0 0 0 695 5.0000 B51 B53 B55 S

새 column 추가하기

  • [] 사용하여 추가하기

  • insert 함수 사용하여 원하는 위치에 추가하기

train_data['Age_double'] = train_data['Age'] * 2

train_data.head()
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked Age_double
0 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S 44.0
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C 76.0
2 3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S 52.0
3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S 70.0
4 5 0 3 Allen, Mr. William Henry male 35.0 0 0 373450 8.0500 NaN S 70.0



train_data['Age_tripple'] = train_data['Age_double'] + train_data['Age']

train_data.head()
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked Age_double Age_tripple
0 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S 44.0 66.0
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C 76.0 114.0
2 3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S 52.0 78.0
3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S 70.0 105.0
4 5 0 3 Allen, Mr. William Henry male 35.0 0 0 373450 8.0500 NaN S 70.0 105.0



train_data.insert(3, 'Fare10', train_data['Fare'] / 10) # insert : 특정 열에 넣기 

train_data.head()
PassengerId Survived Pclass Fare10 Name Sex Age SibSp Parch Ticket Fare Cabin Embarked Age_double Age_tripple
0 1 0 3 0.72500 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S 44.0 66.0
1 2 1 1 7.12833 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C 76.0 114.0
2 3 1 3 0.79250 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S 52.0 78.0
3 4 1 1 5.31000 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S 70.0 105.0
4 5 0 3 0.80500 Allen, Mr. William Henry male 35.0 0 0 373450 8.0500 NaN S 70.0 105.0



column 삭제하기

  • drop 함수 사용하여 삭제

    • 리스트를 사용하여 멀티플 삭제 가능
train_data.drop('Age_tripple', axis=1) # axis =0 은 행레벨, 1은 열레벨

train_data.head() 

# 보면 알겠지만 대부분의 함수들은 복사본에 적용. 원본 데이터는 건들지 않는다.
PassengerId Survived Pclass Fare10 Name Sex Age SibSp Parch Ticket Fare Cabin Embarked Age_double Age_tripple
0 1 0 3 0.72500 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S 44.0 66.0
1 2 1 1 7.12833 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C 76.0 114.0
2 3 1 3 0.79250 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S 52.0 78.0
3 4 1 1 5.31000 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S 70.0 105.0
4 5 0 3 0.80500 Allen, Mr. William Henry male 35.0 0 0 373450 8.0500 NaN S 70.0 105.0



train_data.drop(['Age_double', 'Age_tripple'], axis=1)
PassengerId Survived Pclass Fare10 Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 1 0 3 0.72500 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S
1 2 1 1 7.12833 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C
2 3 1 3 0.79250 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S
3 4 1 1 5.31000 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S
4 5 0 3 0.80500 Allen, Mr. William Henry male 35.0 0 0 373450 8.0500 NaN S
... ... ... ... ... ... ... ... ... ... ... ... ... ...
886 887 0 2 1.30000 Montvila, Rev. Juozas male 27.0 0 0 211536 13.0000 NaN S
887 888 1 1 3.00000 Graham, Miss. Margaret Edith female 19.0 0 0 112053 30.0000 B42 S
888 889 0 3 2.34500 Johnston, Miss. Catherine Helen "Carrie" female NaN 1 2 W./C. 6607 23.4500 NaN S
889 890 1 1 3.00000 Behr, Mr. Karl Howell male 26.0 0 0 111369 30.0000 C148 C
890 891 0 3 0.77500 Dooley, Mr. Patrick male 32.0 0 0 370376 7.7500 NaN Q

891 rows × 13 columns



train_data.drop(['Age_double', 'Age_tripple'], axis=1, inplace=True)

# inplace하면 원본에 저장
train_data
PassengerId Survived Pclass Fare10 Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 1 0 3 0.72500 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S
1 2 1 1 7.12833 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C
2 3 1 3 0.79250 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S
3 4 1 1 5.31000 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S
4 5 0 3 0.80500 Allen, Mr. William Henry male 35.0 0 0 373450 8.0500 NaN S
... ... ... ... ... ... ... ... ... ... ... ... ... ...
886 887 0 2 1.30000 Montvila, Rev. Juozas male 27.0 0 0 211536 13.0000 NaN S
887 888 1 1 3.00000 Graham, Miss. Margaret Edith female 19.0 0 0 112053 30.0000 B42 S
888 889 0 3 2.34500 Johnston, Miss. Catherine Helen "Carrie" female NaN 1 2 W./C. 6607 23.4500 NaN S
889 890 1 1 3.00000 Behr, Mr. Karl Howell male 26.0 0 0 111369 30.0000 C148 C
890 891 0 3 0.77500 Dooley, Mr. Patrick male 32.0 0 0 370376 7.7500 NaN Q

891 rows × 13 columns



변수의 상관관계

  • 이 두변수간의 흐름이 얼마나 비슷한가를 나타내는 척도 (증가, 감소) 그 폭이 얼마나 비슷하냐
  • 두 변수간의 패턴을 본다.
  • 인과관계는 일수도 있고 아닐 수도 있다.
train_data = pd.read_csv('F:/data/titanic/train.csv')

train_data.head()
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C
2 3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S
3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S
4 5 0 3 Allen, Mr. William Henry male 35.0 0 0 373450 8.0500 NaN S



변수(column) 사이의 상관계수(correlation)

  • corr함수를 통해 상관계수 연산 (-1, 1 사이의 결과)

    • 연속성(숫자형)데이터에 대해서만 연산

    • 인과관계를 의미하진 않음

train_data.corr()
PassengerId Survived Pclass Age SibSp Parch Fare
PassengerId 1.000000 -0.005007 -0.035144 0.036847 -0.057527 -0.001652 0.012658
Survived -0.005007 1.000000 -0.338481 -0.077221 -0.035322 0.081629 0.257307
Pclass -0.035144 -0.338481 1.000000 -0.369226 0.083081 0.018443 -0.549500
Age 0.036847 -0.077221 -0.369226 1.000000 -0.308247 -0.189119 0.096067
SibSp -0.057527 -0.035322 0.083081 -0.308247 1.000000 0.414838 0.159651
Parch -0.001652 0.081629 0.018443 -0.189119 0.414838 1.000000 0.216225
Fare 0.012658 0.257307 -0.549500 0.096067 0.159651 0.216225 1.000000



plt.matshow(train_data.corr()) #색깔이 밝을수록 관련이 깊다.

pandas_org_120_1

train_data.isna() # True인 경우 NaN이다.
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 False False False False False False False False False False True False
1 False False False False False False False False False False False False
2 False False False False False False False False False False True False
3 False False False False False False False False False False False False
4 False False False False False False False False False False True False
... ... ... ... ... ... ... ... ... ... ... ... ...
886 False False False False False False False False False False True False
887 False False False False False False False False False False False False
888 False False False False False True False False False False True False
889 False False False False False False False False False False False False
890 False False False False False False False False False False True False

891 rows × 12 columns



train_data['Age'].isna()
0      False
1      False
2      False
3      False
4      False
       ...  
886    False
887    False
888     True
889    False
890    False
Name: Age, Length: 891, dtype: bool



NaN 처리 방법

  • 데이터에서 삭제

    • dropna 함수
  • 다른 값으로 치환

    • fillna 함수
  • NaN 데이터 삭제하기

train_data.dropna() # 한개라도 NaN이 있다면 그 row를 지워버린다.
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C
3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S
6 7 0 1 McCarthy, Mr. Timothy J male 54.0 0 0 17463 51.8625 E46 S
10 11 1 3 Sandstrom, Miss. Marguerite Rut female 4.0 1 1 PP 9549 16.7000 G6 S
11 12 1 1 Bonnell, Miss. Elizabeth female 58.0 0 0 113783 26.5500 C103 S
... ... ... ... ... ... ... ... ... ... ... ... ...
871 872 1 1 Beckwith, Mrs. Richard Leonard (Sallie Monypeny) female 47.0 1 1 11751 52.5542 D35 S
872 873 0 1 Carlsson, Mr. Frans Olof male 33.0 0 0 695 5.0000 B51 B53 B55 S
879 880 1 1 Potter, Mrs. Thomas Jr (Lily Alexenia Wilson) female 56.0 0 1 11767 83.1583 C50 C
887 888 1 1 Graham, Miss. Margaret Edith female 19.0 0 0 112053 30.0000 B42 S
889 890 1 1 Behr, Mr. Karl Howell male 26.0 0 0 111369 30.0000 C148 C

183 rows × 12 columns



train_data.dropna(subset=['Age', 'Cabin']) # subset : 특정 열의 NaN만 판단
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C
3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S
6 7 0 1 McCarthy, Mr. Timothy J male 54.0 0 0 17463 51.8625 E46 S
10 11 1 3 Sandstrom, Miss. Marguerite Rut female 4.0 1 1 PP 9549 16.7000 G6 S
11 12 1 1 Bonnell, Miss. Elizabeth female 58.0 0 0 113783 26.5500 C103 S
... ... ... ... ... ... ... ... ... ... ... ... ...
871 872 1 1 Beckwith, Mrs. Richard Leonard (Sallie Monypeny) female 47.0 1 1 11751 52.5542 D35 S
872 873 0 1 Carlsson, Mr. Frans Olof male 33.0 0 0 695 5.0000 B51 B53 B55 S
879 880 1 1 Potter, Mrs. Thomas Jr (Lily Alexenia Wilson) female 56.0 0 1 11767 83.1583 C50 C
887 888 1 1 Graham, Miss. Margaret Edith female 19.0 0 0 112053 30.0000 B42 S
889 890 1 1 Behr, Mr. Karl Howell male 26.0 0 0 111369 30.0000 C148 C

185 rows × 12 columns



train_data.dropna(axis=1) # 컬럼 중에 NaN이 있다면 지워버려라
PassengerId Survived Pclass Name Sex SibSp Parch Ticket Fare
0 1 0 3 Braund, Mr. Owen Harris male 1 0 A/5 21171 7.2500
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 1 0 PC 17599 71.2833
2 3 1 3 Heikkinen, Miss. Laina female 0 0 STON/O2. 3101282 7.9250
3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 1 0 113803 53.1000
4 5 0 3 Allen, Mr. William Henry male 0 0 373450 8.0500
... ... ... ... ... ... ... ... ... ...
886 887 0 2 Montvila, Rev. Juozas male 0 0 211536 13.0000
887 888 1 1 Graham, Miss. Margaret Edith female 0 0 112053 30.0000
888 889 0 3 Johnston, Miss. Catherine Helen "Carrie" female 1 2 W./C. 6607 23.4500
889 890 1 1 Behr, Mr. Karl Howell male 0 0 111369 30.0000
890 891 0 3 Dooley, Mr. Patrick male 0 0 370376 7.7500

891 rows × 9 columns



NaN 값 대체하기

  • 평균으로 대체하기

  • 생존자/사망자 별 평균으로 대체하기

train_data['Age'].fillna(train_data['Age'].mean())

#평균을 구하고 결측값에 넣는다. 

# # inplace=False : 결과 반환 # inplace=True : 원본 데이터에 적용
0      22.000000
1      38.000000
2      26.000000
3      35.000000
4      35.000000
         ...    
886    27.000000
887    19.000000
888    29.699118
889    26.000000
890    32.000000
Name: Age, Length: 891, dtype: float64



# 생존자 나이 평균

mean1 = train_data[train_data['Survived'] == 1]['Age'].mean()



# 사망자 나이 평균

mean0 = train_data[train_data['Survived'] == 0]['Age'].mean()



print(mean1, mean0)
28.343689655172415 30.62617924528302



train_data[train_data['Survived'] == 1]['Age'].fillna(mean1)

train_data[train_data['Survived'] == 0]['Age'].fillna(mean0)
0      22.000000
4      35.000000
5      30.626179
6      54.000000
7       2.000000
         ...    
884    25.000000
885    39.000000
886    27.000000
888    30.626179
890    32.000000
Name: Age, Length: 549, dtype: float64



train_data.loc[train_data['Survived'] == 1, 'Age'] = train_data[train_data['Survived'] == 1]['Age'].fillna(mean1)

train_data.loc[train_data['Survived'] == 0, 'Age'] = train_data[train_data['Survived'] == 0]['Age'].fillna(mean0)
train_data = pd.read_csv('E:\kaggle/titanic/train.csv')
# numpy와 pandas를 쓸때는 최대한 loop를 지양해야 한다.



Pclass 변수 변환하기

  • astype 사용하여 간단히 타입만 변환
train_data['Pclass'] = train_data['Pclass'].astype(str)



Age 변수 변환하기

  • 변환 로직을 함수로 만든 후, apply 함수로 적용
def age_categorize(age): #연령대별로 나타내기

    if math.isnan(age):

        return -1

    return math.floor(age / 10) * 10



train_data['Age'].apply(age_categorize)

# apply변수는 해당 컬럼의 모든 값에 다 적용시켜준다.
0      20
1      30
2      20
3      30
4      30
       ..
886    20
887    10
888    -1
889    20
890    30
Name: Age, Length: 891, dtype: int64



One-hot encoding

  • 범주형 데이터는 분석단계에서 계산이 어렵기 때문에 숫자형으로 변경이 필요함

  • 범주형 데이터의 각 범주(category)를 column레벨로 변경

  • 해당 범주에 해당하면 1, 아니면 0으로 채우는 인코딩 기법

  • pandas.get_dummies 함수 사용

    • drop_first : 첫번째 카테고리 값은 사용하지 않음
pd.get_dummies(train_data, columns=['Pclass', 'Sex', 'Embarked'], drop_first=False) 

# columns : 바꾸고자 하는 컬럼만
PassengerId Survived Name Age SibSp Parch Ticket Fare Cabin Pclass_1 Pclass_2 Pclass_3 Sex_female Sex_male Embarked_C Embarked_Q Embarked_S
0 1 0 Braund, Mr. Owen Harris 22.0 1 0 A/5 21171 7.2500 NaN 0 0 1 0 1 0 0 1
1 2 1 Cumings, Mrs. John Bradley (Florence Briggs Th... 38.0 1 0 PC 17599 71.2833 C85 1 0 0 1 0 1 0 0
2 3 1 Heikkinen, Miss. Laina 26.0 0 0 STON/O2. 3101282 7.9250 NaN 0 0 1 1 0 0 0 1
3 4 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) 35.0 1 0 113803 53.1000 C123 1 0 0 1 0 0 0 1
4 5 0 Allen, Mr. William Henry 35.0 0 0 373450 8.0500 NaN 0 0 1 0 1 0 0 1
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
886 887 0 Montvila, Rev. Juozas 27.0 0 0 211536 13.0000 NaN 0 1 0 0 1 0 0 1
887 888 1 Graham, Miss. Margaret Edith 19.0 0 0 112053 30.0000 B42 1 0 0 1 0 0 0 1
888 889 0 Johnston, Miss. Catherine Helen "Carrie" NaN 1 2 W./C. 6607 23.4500 NaN 0 0 1 1 0 0 0 1
889 890 1 Behr, Mr. Karl Howell 26.0 0 0 111369 30.0000 C148 1 0 0 0 1 1 0 0
890 891 0 Dooley, Mr. Patrick 32.0 0 0 370376 7.7500 NaN 0 0 1 0 1 0 1 0

891 rows × 17 columns



pd.get_dummies(train_data, columns=['Pclass', 'Sex', 'Embarked'], drop_first=True)
PassengerId Survived Name Age SibSp Parch Ticket Fare Cabin Pclass_2 Pclass_3 Sex_male Embarked_Q Embarked_S
0 1 0 Braund, Mr. Owen Harris 22.0 1 0 A/5 21171 7.2500 NaN 0 1 1 0 1
1 2 1 Cumings, Mrs. John Bradley (Florence Briggs Th... 38.0 1 0 PC 17599 71.2833 C85 0 0 0 0 0
2 3 1 Heikkinen, Miss. Laina 26.0 0 0 STON/O2. 3101282 7.9250 NaN 0 1 0 0 1
3 4 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) 35.0 1 0 113803 53.1000 C123 0 0 0 0 1
4 5 0 Allen, Mr. William Henry 35.0 0 0 373450 8.0500 NaN 0 1 1 0 1
... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
886 887 0 Montvila, Rev. Juozas 27.0 0 0 211536 13.0000 NaN 1 0 1 0 1
887 888 1 Graham, Miss. Margaret Edith 19.0 0 0 112053 30.0000 B42 0 0 0 0 1
888 889 0 Johnston, Miss. Catherine Helen "Carrie" NaN 1 2 W./C. 6607 23.4500 NaN 0 1 0 0 1
889 890 1 Behr, Mr. Karl Howell 26.0 0 0 111369 30.0000 C148 0 0 1 0 0
890 891 0 Dooley, Mr. Patrick 32.0 0 0 370376 7.7500 NaN 0 1 1 1 0

891 rows × 14 columns



group by

  • 아래의 세 단계를 적용하여 데이터를 그룹화(groupping) (SQL의 group by 와 개념적으로는 동일, 사용법은 유사)

    • 데이터 분할

    • operation 적용

    • 데이터 병합



# data 출처: https://www.kaggle.com/hesh97/titanicdataset-traincsv/data

df = pd.read_csv('F:/data/titanic/train.csv')

df.head()
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C
2 3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S
3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S
4 5 0 3 Allen, Mr. William Henry male 35.0 0 0 373450 8.0500 NaN S



GroupBy groups 속성

  • 각 그룹과 그룹에 속한 index를 dict 형태로 표현
class_group = df.groupby('Pclass')

class_group # 이렇게 하면 groupby 객체가 만들어짐
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x000002A260234DF0>
class_group.groups
{1: [1, 3, 6, 11, 23, 27, 30, 31, 34, 35, 52, 54, 55, 61, 62, 64, 83, 88, 92, 96, 97, 102, 110, 118, 124, 136, 137, 139, 151, 155, 166, 168, 170, 174, 177, 185, 187, 194, 195, 209, 215, 218, 224, 230, 245, 248, 252, 256, 257, 258, 262, 263, 268, 269, 270, 273, 275, 284, 290, 291, 295, 297, 298, 299, 305, 306, 307, 309, 310, 311, 318, 319, 325, 329, 331, 332, 334, 336, 337, 339, 341, 351, 356, 366, 369, 370, 373, 375, 377, 380, 383, 390, 393, 412, 430, 434, 435, 438, 445, 447, ...], 2: [9, 15, 17, 20, 21, 33, 41, 43, 53, 56, 58, 66, 70, 72, 78, 84, 98, 99, 117, 120, 122, 123, 133, 134, 135, 144, 145, 148, 149, 150, 161, 178, 181, 183, 190, 191, 193, 199, 211, 213, 217, 219, 221, 226, 228, 232, 234, 236, 237, 238, 239, 242, 247, 249, 259, 265, 272, 277, 288, 292, 303, 308, 312, 314, 316, 317, 322, 323, 327, 340, 342, 343, 344, 345, 346, 357, 361, 385, 387, 389, 397, 398, 399, 405, 407, 413, 416, 417, 418, 426, 427, 432, 437, 439, 440, 443, 446, 450, 458, 463, ...], 3: [0, 2, 4, 5, 7, 8, 10, 12, 13, 14, 16, 18, 19, 22, 24, 25, 26, 28, 29, 32, 36, 37, 38, 39, 40, 42, 44, 45, 46, 47, 48, 49, 50, 51, 57, 59, 60, 63, 65, 67, 68, 69, 71, 73, 74, 75, 76, 77, 79, 80, 81, 82, 85, 86, 87, 89, 90, 91, 93, 94, 95, 100, 101, 103, 104, 105, 106, 107, 108, 109, 111, 112, 113, 114, 115, 116, 119, 121, 125, 126, 127, 128, 129, 130, 131, 132, 138, 140, 141, 142, 143, 146, 147, 152, 153, 154, 156, 157, 158, 159, ...]}
gender_group = df.groupby('Sex')

gender_group.groups
{'female': [1, 2, 3, 8, 9, 10, 11, 14, 15, 18, 19, 22, 24, 25, 28, 31, 32, 38, 39, 40, 41, 43, 44, 47, 49, 52, 53, 56, 58, 61, 66, 68, 71, 79, 82, 84, 85, 88, 98, 100, 106, 109, 111, 113, 114, 119, 123, 128, 132, 133, 136, 140, 141, 142, 147, 151, 156, 161, 166, 167, 172, 177, 180, 184, 186, 190, 192, 194, 195, 198, 199, 205, 208, 211, 215, 216, 218, 229, 230, 233, 235, 237, 240, 241, 246, 247, 251, 254, 255, 256, 257, 258, 259, 264, 268, 269, 272, 274, 275, 276, ...], 'male': [0, 4, 5, 6, 7, 12, 13, 16, 17, 20, 21, 23, 26, 27, 29, 30, 33, 34, 35, 36, 37, 42, 45, 46, 48, 50, 51, 54, 55, 57, 59, 60, 62, 63, 64, 65, 67, 69, 70, 72, 73, 74, 75, 76, 77, 78, 80, 81, 83, 86, 87, 89, 90, 91, 92, 93, 94, 95, 96, 97, 99, 101, 102, 103, 104, 105, 107, 108, 110, 112, 115, 116, 117, 118, 120, 121, 122, 124, 125, 126, 127, 129, 130, 131, 134, 135, 137, 138, 139, 143, 144, 145, 146, 148, 149, 150, 152, 153, 154, 155, ...]}



groupping 함수

  • 그룹 데이터에 적용 가능한 통계 함수(NaN은 제외하여 연산)

  • count - 데이터 개수

  • sum - 데이터의 합

  • mean, std, var - 평균, 표준편차, 분산

  • min, max - 최소, 최대값

class_group.count()
PassengerId Survived Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
Pclass
1 216 216 216 216 186 216 216 216 216 176 214
2 184 184 184 184 173 184 184 184 184 16 184
3 491 491 491 491 355 491 491 491 491 12 491



class_group.mean()['Age'] # 클래스별 나이 평균 계산
Pclass
1    38.233441
2    29.877630
3    25.140620
Name: Age, dtype: float64



class_group.mean()['Survived'] #클래스별 생존자 평균 계산
Pclass
1    0.629630
2    0.472826
3    0.242363
Name: Survived, dtype: float64



# class_group.max() #에러가 난다.

# class_group.min() #에러가 난다.
  • 성별에 따른 생존율 구해보기



df.groupby('Sex').mean()['Survived']
Sex
female    0.742038
male      0.188908
Name: Survived, dtype: float64



복수 columns로 groupping 하기

  • groupby에 column 리스트를 전달

  • 통계함수를 적용한 결과는 multiindex를 갖는 dataframe

  • 클래스와 성별에 따른 생존률 구해보기

df.groupby(['Pclass', 'Sex']).mean()['Survived']
Pclass  Sex   
1       female    0.968085
        male      0.368852
2       female    0.921053
        male      0.157407
3       female    0.500000
        male      0.135447
Name: Survived, dtype: float64
df.groupby(['Pclass', 'Sex']).mean().loc[(2, 'female')]
PassengerId    443.105263
Survived         0.921053
Age             28.722973
SibSp            0.486842
Parch            0.605263
Fare            21.970121
Name: (2, female), dtype: float64
df.groupby(['Pclass', 'Sex']).mean().index
MultiIndex([(1, 'female'),
            (1,   'male'),
            (2, 'female'),
            (2,   'male'),
            (3, 'female'),
            (3,   'male')],
           names=['Pclass', 'Sex'])



index를 이용한 group by

  • index가 있는 경우, groupby 함수에 level 사용 가능

    • level은 index의 depth를 의미하며, 가장 왼쪽부터 0부터 증가
  • set_index 함수

  • column 데이터를 index 레벨로 변경

  • reset_index 함수

  • 인덱스 초기화

df.head()
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C
2 3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S
3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S
4 5 0 3 Allen, Mr. William Henry male 35.0 0 0 373450 8.0500 NaN S



df.set_index(['Pclass', 'Sex']).reset_index()
Pclass Sex PassengerId Survived Name Age SibSp Parch Ticket Fare Cabin Embarked
0 3 male 1 0 Braund, Mr. Owen Harris 22.0 1 0 A/5 21171 7.2500 NaN S
1 1 female 2 1 Cumings, Mrs. John Bradley (Florence Briggs Th... 38.0 1 0 PC 17599 71.2833 C85 C
2 3 female 3 1 Heikkinen, Miss. Laina 26.0 0 0 STON/O2. 3101282 7.9250 NaN S
3 1 female 4 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) 35.0 1 0 113803 53.1000 C123 S
4 3 male 5 0 Allen, Mr. William Henry 35.0 0 0 373450 8.0500 NaN S
... ... ... ... ... ... ... ... ... ... ... ... ...
886 2 male 887 0 Montvila, Rev. Juozas 27.0 0 0 211536 13.0000 NaN S
887 1 female 888 1 Graham, Miss. Margaret Edith 19.0 0 0 112053 30.0000 B42 S
888 3 female 889 0 Johnston, Miss. Catherine Helen "Carrie" NaN 1 2 W./C. 6607 23.4500 NaN S
889 1 male 890 1 Behr, Mr. Karl Howell 26.0 0 0 111369 30.0000 C148 C
890 3 male 891 0 Dooley, Mr. Patrick 32.0 0 0 370376 7.7500 NaN Q

891 rows × 12 columns



df.set_index('Age').groupby(level=0).mean() # level은 인덱스를 뜻함
PassengerId Survived Pclass SibSp Parch Fare
Age
0.42 804.0 1.0 3.0 0.0 1.0 8.5167
0.67 756.0 1.0 2.0 1.0 1.0 14.5000
0.75 557.5 1.0 3.0 2.0 1.0 19.2583
0.83 455.5 1.0 2.0 0.5 1.5 23.8750
0.92 306.0 1.0 1.0 1.0 2.0 151.5500
... ... ... ... ... ... ...
70.00 709.5 0.0 1.5 0.5 0.5 40.7500
70.50 117.0 0.0 3.0 0.0 0.0 7.7500
71.00 295.5 0.0 1.0 0.0 0.0 42.0792
74.00 852.0 0.0 3.0 0.0 0.0 7.7750
80.00 631.0 1.0 1.0 0.0 0.0 30.0000

88 rows × 6 columns



나이대별로 생존율 구하기

def age_categorize(age): #연령별 카테고리화

    if math.isnan(age):

        return -1

    return math.floor(age / 10) * 10
df.set_index('Age').groupby(age_categorize).mean()['Survived']
-1     0.293785
 0     0.612903
 10    0.401961
 20    0.350000
 30    0.437126
 40    0.382022
 50    0.416667
 60    0.315789
 70    0.000000
 80    1.000000
Name: Survived, dtype: float64



MultiIndex를 이용한 groupping

df.set_index(['Pclass', 'Sex']).groupby(level=[0, 1]).mean()['Age'] # level은 인덱스를 뜻함
Pclass  Sex   
1       female    34.611765
        male      41.281386
2       female    28.722973
        male      30.740707
3       female    21.750000
        male      26.507589
Name: Age, dtype: float64



aggregate(집계) 함수 사용하기

  • groupby 결과에 집계함수를 적용하여 그룹별 데이터 확인 가능
df.set_index(['Pclass', 'Sex']).groupby(level=[0, 1]).aggregate([np.mean, np.sum, np.max])
PassengerId Survived Age SibSp Parch Fare
mean sum amax mean sum amax mean sum amax mean sum amax mean sum amax mean sum amax
Pclass Sex
1 female 469.212766 44106 888 0.968085 91 1 34.611765 2942.00 63.0 0.553191 52 3 0.457447 43 2 106.125798 9975.8250 512.3292
male 455.729508 55599 890 0.368852 45 1 41.281386 4169.42 80.0 0.311475 38 3 0.278689 34 4 67.226127 8201.5875 512.3292
2 female 443.105263 33676 881 0.921053 70 1 28.722973 2125.50 57.0 0.486842 37 3 0.605263 46 3 21.970121 1669.7292 65.0000
male 447.962963 48380 887 0.157407 17 1 30.740707 3043.33 70.0 0.342593 37 2 0.222222 24 2 19.741782 2132.1125 73.5000
3 female 399.729167 57561 889 0.500000 72 1 21.750000 2218.50 63.0 0.895833 129 8 0.798611 115 6 16.118810 2321.1086 69.5500
male 455.515850 158064 891 0.135447 47 1 26.507589 6706.42 74.0 0.498559 173 8 0.224784 78 5 12.661633 4393.5865 69.5500



transform 함수

  • groupby 후 transform 함수를 사용하면 원래의 index를 유지한 상태로 통계함수를 적용

  • 전체 데이터의 집계가 아닌 각 그룹에서의 집계를 계산

  • 따라서 새로 생성된 데이터를 원본 dataframe과 합치기 쉬움

df = pd.read_csv('E:\kaggle/titanic/train.csv')
df.groupby('Pclass').mean()
PassengerId Survived Age SibSp Parch Fare
Pclass
1 461.597222 0.629630 38.233441 0.416667 0.356481 84.154687
2 445.956522 0.472826 29.877630 0.402174 0.380435 20.662183
3 439.154786 0.242363 25.140620 0.615071 0.393075 13.675550
df.groupby('Pclass').transform(np.mean)
PassengerId Survived Age SibSp Parch Fare
0 439.154786 0.242363 25.140620 0.615071 0.393075 13.675550
1 461.597222 0.629630 38.233441 0.416667 0.356481 84.154687
2 439.154786 0.242363 25.140620 0.615071 0.393075 13.675550
3 461.597222 0.629630 38.233441 0.416667 0.356481 84.154687
4 439.154786 0.242363 25.140620 0.615071 0.393075 13.675550
... ... ... ... ... ... ...
886 445.956522 0.472826 29.877630 0.402174 0.380435 20.662183
887 461.597222 0.629630 38.233441 0.416667 0.356481 84.154687
888 439.154786 0.242363 25.140620 0.615071 0.393075 13.675550
889 461.597222 0.629630 38.233441 0.416667 0.356481 84.154687
890 439.154786 0.242363 25.140620 0.615071 0.393075 13.675550

891 rows × 6 columns

df['Age2'] = df.groupby('Pclass').transform(np.mean)['Age']

df
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked Age2
0 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S 25.140620
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C 38.233441
2 3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S 25.140620
3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S 38.233441
4 5 0 3 Allen, Mr. William Henry male 35.0 0 0 373450 8.0500 NaN S 25.140620
... ... ... ... ... ... ... ... ... ... ... ... ... ...
886 887 0 2 Montvila, Rev. Juozas male 27.0 0 0 211536 13.0000 NaN S 29.877630
887 888 1 1 Graham, Miss. Margaret Edith female 19.0 0 0 112053 30.0000 B42 S 38.233441
888 889 0 3 Johnston, Miss. Catherine Helen "Carrie" female NaN 1 2 W./C. 6607 23.4500 NaN S 25.140620
889 890 1 1 Behr, Mr. Karl Howell male 26.0 0 0 111369 30.0000 C148 C 38.233441
890 891 0 3 Dooley, Mr. Patrick male 32.0 0 0 370376 7.7500 NaN Q 25.140620

891 rows × 13 columns



df.groupby(['Pclass', 'Sex']).mean()
PassengerId Survived Age SibSp Parch Fare Age2
Pclass Sex
1 female 469.212766 0.968085 34.611765 0.553191 0.457447 106.125798 38.233441
male 455.729508 0.368852 41.281386 0.311475 0.278689 67.226127 38.233441
2 female 443.105263 0.921053 28.722973 0.486842 0.605263 21.970121 29.877630
male 447.962963 0.157407 30.740707 0.342593 0.222222 19.741782 29.877630
3 female 399.729167 0.500000 21.750000 0.895833 0.798611 16.118810 25.140620
male 455.515850 0.135447 26.507589 0.498559 0.224784 12.661633 25.140620



df['Age3'] = df.groupby(['Pclass', 'Sex']).transform(np.mean)['Age']

df
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked Age2 Age3
0 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S 25.140620 26.507589
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C 38.233441 34.611765
2 3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S 25.140620 21.750000
3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S 38.233441 34.611765
4 5 0 3 Allen, Mr. William Henry male 35.0 0 0 373450 8.0500 NaN S 25.140620 26.507589
... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
886 887 0 2 Montvila, Rev. Juozas male 27.0 0 0 211536 13.0000 NaN S 29.877630 30.740707
887 888 1 1 Graham, Miss. Margaret Edith female 19.0 0 0 112053 30.0000 B42 S 38.233441 34.611765
888 889 0 3 Johnston, Miss. Catherine Helen "Carrie" female NaN 1 2 W./C. 6607 23.4500 NaN S 25.140620 21.750000
889 890 1 1 Behr, Mr. Karl Howell male 26.0 0 0 111369 30.0000 C148 C 38.233441 41.281386
890 891 0 3 Dooley, Mr. Patrick male 32.0 0 0 370376 7.7500 NaN Q 25.140620 26.507589

891 rows × 14 columns

  1. pivot, pivot_table 함수의 이해
df = pd.DataFrame({

    '지역': ['서울', '서울', '서울', '경기', '경기', '부산', '서울', '서울', '부산', '경기', '경기', '경기'],

    '요일': ['월요일', '화요일', '수요일', '월요일', '화요일', '월요일', '목요일', '금요일', '화요일', '수요일', '목요일', '금요일'],

    '강수량': [100, 80, 1000, 200, 200, 100, 50, 100, 200, 100, 50, 100],

    '강수확률': [80, 70, 90, 10, 20, 30, 50, 90, 20, 80, 50, 10]

                  })



df
지역 요일 강수량 강수확률
0 서울 월요일 100 80
1 서울 화요일 80 70
2 서울 수요일 1000 90
3 경기 월요일 200 10
4 경기 화요일 200 20
5 부산 월요일 100 30
6 서울 목요일 50 50
7 서울 금요일 100 90
8 부산 화요일 200 20
9 경기 수요일 100 80
10 경기 목요일 50 50
11 경기 금요일 100 10



pivot

  • dataframe의 형태를 변경

  • 인덱스, 컬럼, 데이터로 사용할 컬럼을 명시

# 피벗은 보기 좋게



df.pivot('지역', '요일') # 지역이 index, 요일이 columns

#에러
강수량 강수확률
요일 금요일 목요일 수요일 월요일 화요일 금요일 목요일 수요일 월요일 화요일
지역
경기 100.0 50.0 100.0 200.0 200.0 10.0 50.0 80.0 10.0 20.0
부산 NaN NaN NaN 100.0 200.0 NaN NaN NaN 30.0 20.0
서울 100.0 50.0 1000.0 100.0 80.0 90.0 50.0 90.0 80.0 70.0



df.pivot('요일', '지역')
강수량 강수확률
지역 경기 부산 서울 경기 부산 서울
요일
금요일 100.0 NaN 100.0 10.0 NaN 90.0
목요일 50.0 NaN 50.0 50.0 NaN 50.0
수요일 100.0 NaN 1000.0 80.0 NaN 90.0
월요일 200.0 100.0 100.0 10.0 30.0 80.0
화요일 200.0 200.0 80.0 20.0 20.0 70.0



pivot_table

  • 기능적으로 pivot과 동일

  • pivot과의 차이점

    • 중복되는 모호한 값이 있을 경우, aggregation 함수 사용하여 값을 채움
pd.pivot_table(df,index='요일', columns='지역', aggfunc=np.mean)
강수량 강수확률
지역 경기 부산 서울 경기 부산 서울
요일
금요일 100.0 NaN 100.0 10.0 NaN 90.0
목요일 50.0 NaN 50.0 50.0 NaN 50.0
수요일 100.0 NaN 1000.0 80.0 NaN 90.0
월요일 200.0 100.0 100.0 10.0 30.0 80.0
화요일 200.0 200.0 80.0 20.0 20.0 70.0



stack & unstack

  • stack : 컬럼 레벨에서 인덱스 레벨로 dataframe 변경

  • 즉, 데이터를 쌓아올리는 개념으로 이해하면 쉬움

  • unstack : 인덱스 레벨에서 컬럼 레벨로 dataframe 변경

  • stack의 반대 operation

  • 둘은 역의 관계에 있음

new_df = df.set_index(['지역', '요일'])

new_df
강수량 강수확률
지역 요일
서울 월요일 100 80
화요일 80 70
수요일 1000 90
경기 월요일 200 10
화요일 200 20
부산 월요일 100 30
서울 목요일 50 50
금요일 100 90
부산 화요일 200 20
경기 수요일 100 80
목요일 50 50
금요일 100 10
new_df.unstack(0) # 0이면 지역 인덱스를 컬럼레벨로 올려라
강수량 강수확률
지역 경기 부산 서울 경기 부산 서울
요일
금요일 100.0 NaN 100.0 10.0 NaN 90.0
목요일 50.0 NaN 50.0 50.0 NaN 50.0
수요일 100.0 NaN 1000.0 80.0 NaN 90.0
월요일 200.0 100.0 100.0 10.0 30.0 80.0
화요일 200.0 200.0 80.0 20.0 20.0 70.0
new_df.unstack(1) # 1이면 요일 인덱스를 컬럼레벨로 올려라
강수량 강수확률
요일 금요일 목요일 수요일 월요일 화요일 금요일 목요일 수요일 월요일 화요일
지역
경기 100.0 50.0 100.0 200.0 200.0 10.0 50.0 80.0 10.0 20.0
부산 NaN NaN NaN 100.0 200.0 NaN NaN NaN 30.0 20.0
서울 100.0 50.0 1000.0 100.0 80.0 90.0 50.0 90.0 80.0 70.0



new_df.unstack(0).stack(0)
지역 경기 부산 서울
요일
금요일 강수량 100.0 NaN 100.0
강수확률 10.0 NaN 90.0
목요일 강수량 50.0 NaN 50.0
강수확률 50.0 NaN 50.0
수요일 강수량 100.0 NaN 1000.0
강수확률 80.0 NaN 90.0
월요일 강수량 200.0 100.0 100.0
강수확률 10.0 30.0 80.0
화요일 강수량 200.0 200.0 80.0
강수확률 20.0 20.0 70.0
new_df.unstack(0).stack(1) #-1은 마지막
강수량 강수확률
요일 지역
금요일 경기 100.0 10.0
서울 100.0 90.0
목요일 경기 50.0 50.0
서울 50.0 50.0
수요일 경기 100.0 80.0
서울 1000.0 90.0
월요일 경기 200.0 10.0
부산 100.0 30.0
서울 100.0 80.0
화요일 경기 200.0 20.0
부산 200.0 20.0
서울 80.0 70.0



concat 함수 사용하여 dataframe 병합하기

  • pandas.concat 함수

  • 축을 따라 dataframe을 병합 가능

    • 기본 axis = 0 -> 행단위 병합
  • column명이 같은 경우

# concat은 단순하게 합침
df1 = pd.DataFrame({'key1' : np.arange(10), 'value1' : np.random.randn(10)})
df2 = pd.DataFrame({'key1' : np.arange(10), 'value1' : np.random.randn(10)})
pd.concat([df1, df2], ignore_index=True) # index는 유지. 하지만 ignore_index쓰면 바뀜


key1 value1
0 0 -0.112312
1 1 0.611798
2 2 0.189342
3 3 -1.027669
4 4 -1.069512
5 5 -1.680114
6 6 -1.338902
7 7 0.449318
8 8 0.273951
9 9 1.077814
10 0 0.281915
11 1 0.320075
12 2 -0.296429
13 3 -1.420309
14 4 -0.847101
15 5 -0.518147
16 6 -0.082555
17 7 -0.254324
18 8 -0.977181
19 9 0.265628
pd.concat([df1, df2], axis=1)
key1 value1 key1 value1
0 0 -0.112312 0 0.281915
1 1 0.611798 1 0.320075
2 2 0.189342 2 -0.296429
3 3 -1.027669 3 -1.420309
4 4 -1.069512 4 -0.847101
5 5 -1.680114 5 -0.518147
6 6 -1.338902 6 -0.082555
7 7 0.449318 7 -0.254324
8 8 0.273951 8 -0.977181
9 9 1.077814 9 0.265628



column 명이 다른 경우

df3 = pd.DataFrame({'key2' : np.arange(10), 'value2' : np.random.randn(10)})
pd.concat([df1, df3], axis=1)
key1 value1 key2 value2
0 0 -0.112312 0 -1.300134
1 1 0.611798 1 0.530596
2 2 0.189342 2 0.032435
3 3 -1.027669 3 0.269433
4 4 -1.069512 4 -0.216506
5 5 -1.680114 5 0.110930
6 6 -1.338902 6 -0.371537
7 7 0.449318 7 0.522430
8 8 0.273951 8 -2.454415
9 9 1.077814 9 -0.803864



dataframe merge

  • SQL의 join처럼 특정한 column을 기준으로 병합

    • join 방식: how 파라미터를 통해 명시

      • inner: 기본값, 일치하는 값이 있는 경우

      • left: left outer join

      • right: right outer join

      • outer: full outer join

  • pandas.merge 함수가 사용됨

customer = pd.DataFrame({'customer_id' : np.arange(6), 

                    'name' : ['철수'"", '영희', '길동', '영수', '수민', '동건'], 

                    '나이' : [40, 20, 21, 30, 31, 18]})



customer
customer_id name 나이
0 0 철수 40
1 1 영희 20
2 2 길동 21
3 3 영수 30
4 4 수민 31
5 5 동건 18
orders = pd.DataFrame({'customer_id' : [1, 1, 2, 2, 2, 3, 3, 1, 4, 9], 

                    'item' : ['치약', '칫솔', '이어폰', '헤드셋', '수건', '생수', '수건', '치약', '생수', '케이스'], 

                    'quantity' : [1, 2, 1, 1, 3, 2, 2, 3, 2, 1]})

orders.head()
customer_id item quantity
0 1 치약 1
1 1 칫솔 2
2 2 이어폰 1
3 2 헤드셋 1
4 2 수건 3



on

  • join 대상이 되는 column 명시
pd.merge(customer, orders, on='customer_id', how='inner') # customer_id를 기준으로

# 일치하는 것만 가져옴

# on은 머지를 하게 될 대상, 컬럼을 명시

# how은 어떤 식으로 머지를 할 것인지
customer_id name 나이 item quantity
0 1 영희 20 치약 1
1 1 영희 20 칫솔 2
2 1 영희 20 치약 3
3 2 길동 21 이어폰 1
4 2 길동 21 헤드셋 1
5 2 길동 21 수건 3
6 3 영수 30 생수 2
7 3 영수 30 수건 2
8 4 수민 31 생수 2



pd.merge(customer, orders, on='customer_id', how='left')
customer_id name 나이 item quantity
0 0 철수 40 NaN NaN
1 1 영희 20 치약 1.0
2 1 영희 20 칫솔 2.0
3 1 영희 20 치약 3.0
4 2 길동 21 이어폰 1.0
5 2 길동 21 헤드셋 1.0
6 2 길동 21 수건 3.0
7 3 영수 30 생수 2.0
8 3 영수 30 수건 2.0
9 4 수민 31 생수 2.0
10 5 동건 18 NaN NaN
pd.merge(customer, orders, on='customer_id', how='right')
customer_id name 나이 item quantity
0 1 영희 20.0 치약 1
1 1 영희 20.0 칫솔 2
2 1 영희 20.0 치약 3
3 2 길동 21.0 이어폰 1
4 2 길동 21.0 헤드셋 1
5 2 길동 21.0 수건 3
6 3 영수 30.0 생수 2
7 3 영수 30.0 수건 2
8 4 수민 31.0 생수 2
9 9 NaN NaN 케이스 1
pd.merge(customer, orders, on='customer_id', how='outer')

# outer는 left와 right을 합친 것
customer_id name 나이 item quantity
0 0 철수 40.0 NaN NaN
1 1 영희 20.0 치약 1.0
2 1 영희 20.0 칫솔 2.0
3 1 영희 20.0 치약 3.0
4 2 길동 21.0 이어폰 1.0
5 2 길동 21.0 헤드셋 1.0
6 2 길동 21.0 수건 3.0
7 3 영수 30.0 생수 2.0
8 3 영수 30.0 수건 2.0
9 4 수민 31.0 생수 2.0
10 5 동건 18.0 NaN NaN
11 9 NaN NaN 케이스 1.0
cust1 = customer.set_index('customer_id')

order1 = orders.set_index('customer_id')
cust1
name 나이
customer_id
0 철수 40
1 영희 20
2 길동 21
3 영수 30
4 수민 31
5 동건 18
order1
item quantity
customer_id
1 치약 1
1 칫솔 2
2 이어폰 1
2 헤드셋 1
2 수건 3
3 생수 2
3 수건 2
1 치약 3
4 생수 2
9 케이스 1
pd.merge(cust1, order1, left_index=True, right_index=True)

# on을 설정할 필요가 없음
name 나이 item quantity
customer_id
1 영희 20 치약 1
1 영희 20 칫솔 2
1 영희 20 치약 3
2 길동 21 이어폰 1
2 길동 21 헤드셋 1
2 길동 21 수건 3
3 영수 30 생수 2
3 영수 30 수건 2
4 수민 31 생수 2



# 가장 많이 팔린 아이템은?

pd.merge(customer, orders, on='customer_id').groupby('item').sum().sort_values(by='quantity', ascending=False)



# 수건이 가장 많이 팔림 
customer_id 나이 quantity
item
수건 5 51 5
생수 7 61 4
치약 2 40 4
칫솔 1 20 2
이어폰 2 21 1
헤드셋 2 21 1
#영희가 가장 많이 구매한 아이템은?

pd.merge(customer, orders, on='customer_id').groupby(['name', 'item']).sum().loc['영희', 'quantity']
item
치약    4
칫솔    2
Name: quantity, dtype: int64



join 함수

  • 내부적으로 pandas.merge 함수 사용

  • 기본적으로 index를 사용하여 left join

cust1.join(order1, how='inner')
name 나이 item quantity
customer_id
1 영희 20 치약 1
1 영희 20 칫솔 2
1 영희 20 치약 3
2 길동 21 이어폰 1
2 길동 21 헤드셋 1
2 길동 21 수건 3
3 영수 30 생수 2
3 영수 30 수건 2
4 수민 31 생수 2

댓글남기기