데이터 - > 재구조화 , 피봇 , 멜팅, 내가 원하는 형태로 데이터의 구조를 변경

피봇, 피봇 테이블 약간 다르다, 피봇 테이블이 피봇함수를 포괄한다.

피봇 테이블,스택, 언스택, 크로스 테이블, 멜트, widetolong 등의 함수가 있다.

스택 => 위에서 아래로 쌓을떄, 언스택 => 쌓여져있는데이터를 좌 - 우로 나열할때,

피봇 테이블 =>

In [0]:
df = pd.DataFrame({
    'c_id' : [ 'c1','c1','c1', 'c2','c2','c2', 'c3','c3','c3' ],
    'p_id' : [ 'p1','p2','p3', 'p1','p2','p3', 'p1','p2','p3' ],
    'amount' : [ 20, 10, 0, 30, 20, 30, 0, 5, 10 ]
})

df
Out[0]:
c_idp_idamount
0c1p120
1c1p210
2c1p30
3c2p130
4c2p220
5c2p330
6c3p10
7c3p25
8c3p310
In [0]:
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 9 entries, 0 to 8
Data columns (total 3 columns):
c_id      9 non-null object
p_id      9 non-null object
amount    9 non-null int64
dtypes: int64(1), object(2)
memory usage: 296.0+ bytes

c_id를 행으로 하고 싶다, => 3개의 행이 나온다,

p_id를 열로 하고 싶다 => 3 * 3 행렬 에다가 amount 값을 넣자.

테이블을 완전 재 구조화.

In [0]:
#df.pivot(행 인덱스 , 열 이름 , 각 셀에 들어갈 값)

df.pivot( index = 'c_id', columns = 'p_id', values = 'amount')
Out[0]:
p_idp1p2p3
c_id
c120100
c2302030
c30510
In [0]:
#df.pivot(행 인덱스 , 열 이름 , 각 셀에 들어갈 값)
df.pivot_table( index = 'c_id', columns = 'p_id', values = 'amount')
Out[0]:
p_idp1p2p3
c_id
c120100
c2302030
c30510

인덱스가 c_id처럼 하나만 줄떄도 있지만 행 인덱스를 두개이상 줄 떄가 있다. c_id와 'region'같이 두개의 인수로 행 인덱스를 주고자 할때,

두개의 계층으로 표현 하고자 할때, =>중분류, 소분류 같이 카테고리화 할때 쓰게 된다.

시, 동 같이 첫번째 계층을 시로 주고 두번째 계층을 동으로 주게 되면 피봇 테이블만을 써야 한다.

즉, 단순히 재구조화만 할때는 피봇함수를 사용해도 되나 , 피봇테이블의 경우 두개 이상의 변수로 행 인덱스를 삼고자 하는경우.

aggregation(집계) 함수 즉, sum, mean과 같은 그룹단위 함수를 적용하는데에도 차이가 있다.

In [0]:
## 피봇 테이블의 경우 집계함수 사용이 가능하다.

df.pivot_table( index = 'c_id', columns = 'p_id', values = 'amount', aggfunc = np.sum)
Out[0]:
p_idp1p2p3
c_id
c120100
c2302030
c30510
In [0]:
df = pd.DataFrame({
    'c_id' : [ 'c1','c1','c1', 'c2','c2','c2', 'c3','c3','c3' ],
    'p_id' : [ 'p1','p2','p3', 'p1','p2','p3', 'p1','p2','p3' ],
    'amount' : [ 20, 10, 0, 30, 20, 30, 0, 5, 10 ],
    'reg'    : [ 'S','S','S','S','S','S','A','A','A' ]
})

df
Out[0]:
c_idp_idamountreg
0c1p120S
1c1p210S
2c1p30S
3c2p130S
4c2p220S
5c2p330S
6c3p10A
7c3p25A
8c3p310A
In [0]:
#인덱스를 두개로 하고자 하는 경우, c_id 

df.pivot_table( index = ['c_id', 'reg'], columns = 'p_id', values = 'amount', aggfunc = np.sum)
Out[0]:
p_idp1p2p3
c_idreg
c1S20100
c2S302030
c3A0510
In [0]:
## 행 인덱스가 reg인경우 두개 밖에 없으므로 amount에 mean() 함수가 적용 된다. 즉 S - p1에 해당하는 값이 두개가 있을때 그 평균이 들어간다.

df.pivot_table( index = ['reg'], columns = 'p_id', values = 'amount')
Out[0]:
p_idp1p2p3
reg
A0510
S251515
In [0]:
## 기본으로 mean 함수가 적용된다.

df.pivot_table( index = ['reg'], columns = 'p_id', values = 'amount', aggfunc = np.mean)
Out[0]:
p_idp1p2p3
reg
A0510
S251515
In [0]:
## 모든 함수가 전부 사용가능 한다.

df.pivot_table( index = ['reg'], columns = 'p_id', values = 'amount', aggfunc = np.sum)
Out[0]:
p_idp1p2p3
reg
A0510
S503030
In [0]:
df1 = df_csv.copy()
In [0]:
df2 = df_csv.copy()
In [0]:
df3 = df_csv.copy()
In [0]:
df1
Out[0]:
ABCD
0a0b0c0d0
1a1b1c1d1
2a2b2c2d2
3a3b3c3d3
In [0]:
df2
Out[0]:
ABCD
0a4b4c4d4
1a5b5c5d5
2a6b6c6d6
3a7b7c7d7
In [0]:
df3
Out[0]:
ABCD
0a8b8c8d8
1a9b9c9d9
2a10b10c10d10
3a11b11c11d11
In [0]:
row_concat = pd.concat([df1, df2, df3]) # ignore_index = True
In [0]:
row_concat
Out[0]:
ABCD
0a0b0c0d0
1a1b1c1d1
2a2b2c2d2
3a3b3c3d3
0a4b4c4d4
1a5b5c5d5
2a6b6c6d6
3a7b7c7d7
0a8b8c8d8
1a9b9c9d9
2a10b10c10d10
3a11b11c11d11
In [0]:
# row_concat의 4번째 행을 추출 하고자 한다.

# ix는 행 인덱스의 이름을 줄수도 있고 , 행 번호를 줄 수도 있다.
# loc와 iloc를 사용할것. 행 번호로 접근하고자 할때 iloc, 이름으로 접근할때 loc

row_concat.iloc[3, ]
row_concat.iloc[4, ]

row_concat.loc [3, ]
Out[0]:
ABCD
3a3b3c3d3
3a7b7c7d7
3a11b11c11d11
In [0]:
# df1에 시리즈 연결 ( 행 방향으로 연결 xsis = 0 )

new_row_serise = pd.Series( [ 'n1', 'n2', 'n3', 'n4' ] )
Out[0]:
ABCD
0a0b0c0d0
1a1b1c1d1
2a2b2c2d2
3a3b3c3d3
In [0]:
# 아지막 열인 D 오른쪽에다가 시리즈를 붙이고 싶다.

pd.concat( [df1, new_row_serise])
Out[0]:
ABCD0
0a0b0c0d0NaN
1a1b1c1d1NaN
2a2b2c2d2NaN
3a3b3c3d3NaN
0NaNNaNNaNNaNn1
1NaNNaNNaNNaNn2
2NaNNaNNaNNaNn3
3NaNNaNNaNNaNn4
In [0]:
pd.concat( [df1, new_row_serise], axis = 1)
Out[0]:
ABCD0
0a0b0c0d0n1
1a1b1c1d1n2
2a2b2c2d2n3
3a3b3c3d3n4
In [0]:
## 행 한개로 추가하고 싶을때, 시리즈가 아닌 데이터 프레임이어야 제대로 들어간다.

new_row_df = pd.DataFrame( [[ 'n1', 'n2', 'n3', 'n4' ]],
                              columns = [ 'A', 'B', 'C', 'D'] )
In [0]:
pd.concat( [df1, new_row_df], axis = 0)
Out[0]:
ABCD
0a0b0c0d0
1a1b1c1d1
2a2b2c2d2
3a3b3c3d3
0n1n2n3n4

시리즈에는 열 이름이 없기 떄문에, 시리즈를 데이터 프레임의 행으로 연결을 할 수 없었다 시리즈를 데이터 프레임으로 만들때 컬럼 이름을 줘서 행으로 붙일 수 있었다,

즉 시리즈의 경우에는 행, 열 구조가 애매하다.

In [0]:
#연결 하고자 하는 데이터 프레임이 한개일 경우 append를 사용할 수 도 있다.
df1.append(new_row_df)
Out[0]:
ABCD
0a0b0c0d0
1a1b1c1d1
2a2b2c2d2
3a3b3c3d3
0n1n2n3n4

concat의 경우 2개 이상의 데이터 프레임을 모두 합칠 수 있으나 append는 하나씩만 가능.

In [0]:
# 딕셔너리 형태의 자료형을 행에 추가하는법.

data_dict = {'A': 'n2', 'B':'n2','C':'n3','D':'n4'}
In [0]:
## 어펜드 하려면 시리즈가 이름을 가지고 있거나 ignore_index = True를 주면 된다.
df1.append(data_dict, ignore_index = True)
Out[0]:
ABCD
0a0b0c0d0
1a1b1c1d1
2a2b2c2d2
3a3b3c3d3
4n2n2n3n4
In [0]:
rci = pd.concat([df1, df2, df3], ignore_index = True) # ignore_index = True
In [0]:
# 가로로 붙히기.
pd.concat([df1, df2, df3], ignore_index = True, axis = 1)
Out[0]:
01234567891011
0a0b0c0d0a4b4c4d4a8b8c8d8
1a1b1c1d1a5b5c5d5a9b9c9d9
2a2b2c2d2a6b6c6d6a10b10c10d10
3a3b3c3d3a7b7c7d7a11b11c11d11
In [0]:
# 특정 열만 합치기

col_concat = pd.concat([df1, df2, df3], axis = 1)
col_concat

col_concat['A']
Out[0]:
AAA
0a0a4a8
1a1a5a9
2a2a6a10
3a3a7a11

Stack, Unstack

In [0]:
#계층적인 구조(멀티 인덱스)를 만들때 사용하는 클래스.
mi = pd.MultiIndex.from_tuples( [ ('c1', '2019'), ('c1', '2020'),
                            ('c2', '2019'), ('c2', '2020') ])


mi
Out[0]:
MultiIndex(levels=[['c1', 'c2'], ['2019', '2020']],
           codes=[[0, 0, 1, 1], [0, 1, 0, 1]])
In [0]:
pd.DataFrame( np.arange(16).reshape(4,4))
Out[0]:
0123
00123
14567
2891011
312131415
In [0]:
#해당 데이터 프레임을 계층적 행 인덱스로 줄 수 있다.

df = pd.DataFrame( np.arange(16).reshape(4,4), index = mi , columns = [ 'p1', 'p2', 'p3', 'p4'])
In [0]:
df.stack()
Out[0]:
c1  2019  p1     0
          p2     1
          p3     2
          p4     3
    2020  p1     4
          p2     5
          p3     6
          p4     7
c2  2019  p1     8
          p2     9
          p3    10
          p4    11
    2020  p1    12
          p2    13
          p3    14
          p4    15
dtype: int64
In [0]:
## 결과가 시리즈로 나온다.
ds = df.stack()
In [0]:
type(ds)
Out[0]:
pandas.core.series.Series
In [0]:
ds.index
Out[0]:
MultiIndex(levels=[['c1', 'c2'], ['2019', '2020'], ['p1', 'p2', 'p3', 'p4']],
           codes=[[0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1], [0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3]])
In [0]:
## 스택을 하고 난 이후에 계층 단위로 df에 접근이 가능하다.

ds['c1']
Out[0]:
2019  p1    0
      p2    1
      p3    2
      p4    3
2020  p1    4
      p2    5
      p3    6
      p4    7
dtype: int64
In [0]:
ds['c1']['2020']
Out[0]:
p1    4
p2    5
p3    6
p4    7
dtype: int64
In [0]:
ds['c1']['2020'][ ['p2', 'p3']]
Out[0]:
p2    5
p3    6
dtype: int64
In [0]:
#만일 데이터에 결측값이 포함되어 있다면 , 결측값을 빼고 스택을 할지 아니면 그냥 할지 옵션으로 결정 가능

df.ix['c2','p4'] = None
/usr/local/lib/python3.6/dist-packages/ipykernel_launcher.py:2: DeprecationWarning: 
.ix is deprecated. Please use
.loc for label based indexing or
.iloc for positional indexing

See the documentation here:
http://pandas.pydata.org/pandas-docs/stable/indexing.html#ix-indexer-is-deprecated
  
In [0]:
df
Out[0]:
p1p2p3p4
c120190123.0
20204567.0
c220198910NaN
2020121314NaN

스택시 NaN 처리방법

In [0]:
## 기본적으로 NaN은 제외시킨후 스택시킨다.( dropna = True )

df.stack()
Out[0]:
c1  2019  p1     0.0
          p2     1.0
          p3     2.0
          p4     3.0
    2020  p1     4.0
          p2     5.0
          p3     6.0
          p4     7.0
c2  2019  p1     8.0
          p2     9.0
          p3    10.0
    2020  p1    12.0
          p2    13.0
          p3    14.0
dtype: float64
In [0]:
# Nan도 확인 하고자 할때는 
df.stack(dropna = True)
Out[0]:
c1  2019  p1     0.0
          p2     1.0
          p3     2.0
          p4     3.0
    2020  p1     4.0
          p2     5.0
          p3     6.0
          p4     7.0
c2  2019  p1     8.0
          p2     9.0
          p3    10.0
    2020  p1    12.0
          p2    13.0
          p3    14.0
dtype: float64
In [0]:
## Unstack : stack되있는 구조를 다시 해제한다.

ds
Out[0]:
c1  2019  p1     0
          p2     1
          p3     2
          p4     3
    2020  p1     4
          p2     5
          p3     6
          p4     7
c2  2019  p1     8
          p2     9
          p3    10
          p4    11
    2020  p1    12
          p2    13
          p3    14
          p4    15
dtype: int64
In [0]:
ds.unstack()
Out[0]:
p1p2p3p4
c120190123
20204567
c22019891011
202012131415

c1, c2 짜리에 연도가 오고 연도의 자리에 p1, p2, p3, p4 열은 c1, c2, c3, c4로 하겠다, 혹은 C1, C2를 바꾸겠다.

In [0]:
# level = -1 이게 디폴트 0으로 주게 되면  c1, c2가 사라진다. 
ds.unstack( level = 0 )
Out[0]:
c1c2
2019p108
p219
p3210
p4311
2020p1412
p2513
p3614
p4715
In [0]:
# 컬럼과 행 인덱스가 바뀌었다.
ds.unstack( level = 1 )
Out[0]:
20192020
c1p104
p215
p326
p437
c2p1812
p2913
p31014
p41115
In [0]:
# melt = > 특정 컬럼의 이름이 데이터로 들어간다.

df = DataFrame({ 'cid' : ['c1', 'c1', 'c2', 'c2'],
          'pcd' : ['p1', 'p2', 'p1', 'p2'],
           'cid' : [1,2,3,4],
           'pamt' : [10,20,30,40]
           
          })
df
Out[0]:
cidpcdpamt
01p110
12p220
23p130
34p240
In [0]:
# 기존의 컬럼 이름은 날아갔다.열 이름이 variable로 들어간다.

pd.melt(df, id_vars = [ 'cid', 'pcd'], var_name = 'pname', value_name = 'vname' )
Out[0]:
cidpcdpnamevname
01p1pamt10
12p2pamt20
23p1pamt30
34p2pamt40
In [0]:
## 기존의 데이터 프레임에서 피처 4개를 전부다 녹이지 않고  pcnt 와 pamt를 녹이고싶다.

## 특정 컬럼만 녹이기 , 

pd.melt(id_vars = [['cid','pcd'] ], var_name = 'pname')
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-181-e3746cf2f926> in <module>()
      1 
----> 2 pd.melt(id_vars = [['cid','pcd'] ], var_name = 'pname')

TypeError: melt() missing 1 required positional argument: 'frame'
In [0]:
## 크로스 테이블 => 재구조화

df = DataFrame({ 'id' : [ 'id1','id1','id1','id2','id2','id3' ],
                  'd1' :[ 'a','a','a','b','b','b'            ],
                  'd2' :[ 'b','b','b','c','c','d'             ]
              })
                          
df                          
Out[0]:
idd1d2
0id1ab
1id1ab
2id1ab
3id2bc
4id2bc
5id3bd
In [0]:
#d1이 행 인덱스  열인덱스는 d2에있는 cd , 행과열이 만나는 건수가 몇건이 있느냐를 알기 위해서
# 2, 2 a행 ,c 열에는 몇건이 있는지가 들어간다.

pd.crosstab( index = df.d1, columns = df.d2)
Out[0]:
d2bcd
d1
a300
b021
In [0]:
#a와 b가 저장 되어있는d1이 행으로 , d2가 열로, 기존의 데이터 프레임에서 a와 b가 세건 a와 c가 0 건 a와 d가 0 건

# id1에 d1이 a인게 3개 , b인게 0 개 이런식으로 요소의 갯수를 세고자 할때 사용.

pd.crosstab( df.id, columns = df.d1)
Out[0]:
d1ab
id
id130
id202
id301


'딥러닝 모델 설계 > Machine Learning' 카테고리의 다른 글

Day 5. Sort_String_Binomial_Distribution  (0) 2019.07.08
Day 4. Grouping, sorting, visualizing  (0) 2019.07.06
Day 4. binomializing [ OneHotEncoding ]  (0) 2019.07.06
Day 03. Scaler  (0) 2019.07.03
Day 03. Replacement  (0) 2019.07.03

+ Recent posts