Python_Pandas 03

고지현·2023년 6월 24일

Python_Pandas

목록 보기
3/5
post-thumbnail

데이터프레임의 합성

  • numpy 배열을 합치는 것
    • concatenate, vstack(열 사이즈), hstack(행)
    • dstack(m x n), stack(m x n) ... 모양이 맞는 것들을 연결

1:1로 연결

이름전화번호
김제육010-xxxx-xxxx
이김치010-xxxx-xxxx
이름주소
김제육서울시 제육구
이김치경기도 김치시

이름전화번호주소
김제육010-xxxx-xxxx서울시 제육구
이김치010-xxxx-xxxx경기도 김치시

이름 : 공통 열
행 라벨 -> 열, 이름. 행 인덱스
0~10....

1:M 로 연결

이름주소
A서울시
B경기도
C서울시
D울산시
주소지원금
서울시10000
경기도11100
인천시20000

이름주소지원금
A서울시10000
B경기도11100
C서울시10000

merge (두 개 이상의 데이터프레임을 join, 연결)

df1 = pd.DataFrame({
    '고객번호': [1001, 1002, 1003, 1004, 1005, 1006, 1007],
    '이름': ['둘리', '도우너', '또치', '길동', '희동', '마이콜', '영희']
}, columns=['고객번호', '이름'])
df1 # 고객 목록
고객번호	이름
0	1001	둘리
1	1002	도우너
2	1003	또치
3	1004	길동
4	1005	희동
5	1006	마이콜
6	1007	영희
df2 = pd.DataFrame({
    '고객번호': [1001, 1001, 1005, 1006, 1008, 1001],
    '금액': [10000, 20000, 15000, 5000, 100000, 30000]
}, columns=['고객번호', '금액'])
df2 # 구매 기록
고객번호	금액
0	1001	10000
1	1001	20000
2	1005	15000
3	1006	5000
4	1008	100000
5	1001	30000
# merge : 결합하다 -> pandas.merge(df1, df2) # df1 (left), df2 (right)
pd.merge(df1, df2)
고객번호	이름	금액
0	1001	둘리	10000
1	1001	둘리	20000
2	1001	둘리	30000
3	1005	희동	15000
4	1006	마이콜	5000
pd.merge(left = df1, right = df2, on = '고객번호')
고객번호	이름	금액
0	1001	둘리	10000
1	1001	둘리	20000
2	1001	둘리	30000
3	1005	희동	15000
4	1006	마이콜	5000
pd.merge(left = df1, right = df2, on = '고객번호', how = 'inner')
# inner join : (기준되는 열) 양쪽 데이터프레임에 모두 속하는 원소들만 남겨줌(결측치 없는 nan이 안섞인...)
고객번호	    이름	   금액
0	1001	둘리	10000.0
1	1001	둘리	20000.0
2	1001	둘리	30000.0
3	1002	도우너	NaN
4	1003	또치	NaN
5	1004	길동	NaN
6	1005	희동	15000.0
7	1006	마이콜	5000.0
8	1007	영희	NaN``
pd.merge(left = df1, right = df2, on = '고객번호', how = 'outer') # 합집합의 개념
	고객번호	이름	    금액
0	1001	둘리	10000.0
1	1001	둘리	20000.0
2	1001	둘리	30000.0
3	1002	도우너	NaN
4	1003	또치	NaN
5	1004	길동	NaN
6	1005	희동	15000.0
7	1006	마이콜	5000.0
8	1007	영희	NaN
9	1008	NaN	100000.0
pd.merge(left = df1, right = df2, on = '고객번호', how = 'left')
고객번호	    이름	    금액
0	1001	둘리	10000.0
1	1001	둘리	20000.0
2	1001	둘리	30000.0
3	1002	도우너	NaN
4	1003	또치	NaN
5	1004	길동	NaN
6	1005	희동	15000.0
7	1006	마이콜	5000.0
8	1007	영희	NaN
pd.merge(left = df1, right = df2, on = '고객번호', how = 'right')
고객번호	이름	     금액
0	1001	둘리	10000
1	1001	둘리	20000
2	1005	희동	15000
3	1006	마이콜5000
4	1008	NaN	100000
5	1001	둘리	30000

m:n 연결 방식

df1 = pd.DataFrame({
    '품종': ['setosa', 'setosa', 'virginica', 'virginica'],
    '꽃잎길이': [1.4, 1.3, 1.5, 1.3]},
    columns=['품종', '꽃잎길이'])
df1
     품종	꽃잎길이
0	setosa	    1.4
1	setosa	    1.3
2	virginica	1.5
3	virginica	1.3 
df1.품종.value_counts()
setosa       2
virginica    2
Name: 품종, dtype: int64
df2 = pd.DataFrame({
    '품종': ['setosa', 'virginica', 'virginica', 'versicolor'],
    '꽃잎너비': [0.4, 0.3, 0.5, 0.3]},
    columns=['품종', '꽃잎너비'])
df2
품종	꽃잎너비
0	setosa	0.4
1	virginica	0.3
2	virginica	0.5
3	versicolor	0.3
df2.품종.value_counts()
virginica     2
setosa        1
versicolor    1
Name: 품종, dtype: int64
pd.merge(df1, df2)
# 1. 공통으로 존재하는 열을 찾음 (품종)
# 2. 품종들이 몇개씩 있는지 -> 같은 열에 동일한 원소가 여러 개
# -> 원소들끼리의 모든 경우의 수 (조합)을 만들어냄
# 3. inner (df1, df2가 모두 존재하는 걸로만 연결)
품종	꽃잎길이	  꽃잎  너비
0	setosa	   1.4	0.4
1	setosa	   1.3	0.4
2	virginica  1.5	0.3
3	virginica  1.5	0.5
4	virginica  1.3	0.3
5	virginica  1.3	0.5
pd.merge(df1, df2, how="outer")
품종	꽃잎길이	    꽃잎너비
0	setosa	    1.4	0.4
1	setosa	    1.3	0.4
2	virginica	1.5	0.3
3	virginica	1.5	0.5
4	virginica	1.3	0.3
5	virginica	1.3	0.5
6	versicolor	NaN	0.3

연결되면 안되는 열의 이름이 같을 때

# 두 df에서 이름이 같은 열은 모두 연결하는 기준 (키=on)
# 이름은 같아도 키가 되면 안되는 열 => `on` 무엇을 기준을 할지 명시
# (학생) 수업ID / 이름 (학생의 이름)
# (수업) 수업ID / 이름 (수업의 이름)
# -> on=[수업ID, 이름] ??? -> on='수업ID'
df1 = pd.DataFrame({
    '고객명': ['춘향', '춘향', '몽룡'],
    '날짜': ['2018-01-01', '2018-01-02', '2018-01-01'],
    '데이터': ['20000', '30000', '100000']})
df1
고객명	날짜	데이터
0	춘향	2018-01-01	20000
1	춘향	2018-01-02	30000
2	몽룡	2018-01-01	100000
df2 = pd.DataFrame({
    '고객명': ['춘향', '몽룡'],
    '데이터': ['여자', '남자']})
df2
	고객명	데이터
0	춘향	여자
1	몽룡	남자
pd.merge(df1, df2, on=['고객명'])
	고객명	날짜	데이터_x	데이터_y
0	춘향	2018-01-01	20000	여자
1	춘향	2018-01-02	30000	여자
2	몽룡	2018-01-01	100000	남자
pd.merge(df1, df2, on=['고객명'], suffixes=["_L", "_R"])
   고객명	  날짜	데이터_L	데이터_R
0	춘향	2018-01-01	20000	여자
1	춘향	2018-01-02	30000	여자
2	몽룡	2018-01-01	100000	남자

연결하는 기준이 되는 열들의 이름이 다를 때

df1 = pd.DataFrame({
    '이름': ['영희', '철수', '철수'],
    '성적': [1, 2, 3]})
df1
   이름	성적
0	영희	1
1	철수	2
2	철수	3
df2 = pd.DataFrame({
    '성명': ['영희', '영희', '철수'],
    '성적2': [4, 5, 6]})
df2 # df2['이름'] = df2['성명'], df2.drop...['성명']??, rename...
성명	성적2
0	영희	4
1	영희	5
2	철수	6
# pd.merge(df1, df2)
pd.merge(df1, df2, left_on = '이름', right_on = '성명')
이름	성적	성명	성적2
0	영희	1	영희	4
1	영희	1	영희	5
2	철수	2	철수	6
3	철수	3	철수	6

인덱스를 기준으로 합쳐주고 싶을 때

01. 첫번째 방법

df1 = pd.DataFrame({
    '도시': ['서울', '서울', '서울', '부산', '부산'],
    '연도': [2000, 2005, 2010, 2000, 2005],
    '인구': [9853972, 9762546, 9631482, 3655437, 3512547]})
df1
도시	연도	인구
0	서울	2000	9853972
1	서울	2005	9762546
2	서울	2010	9631482
3	부산	2000	3655437
4	부산	2005	3512547
import numpy as np
df2 = pd.DataFrame(
    np.arange(12).reshape((6, 2)),
    index=[['부산', '부산', '서울', '서울', '서울', '서울'],
           [2000, 2005, 2000, 2005, 2010, 2015]],
    columns=['데이터1', '데이터2'])
df2
데이터1	데이터2
부산	2000	0	1
2005	2	3
서울	2000	4	5
2005	6	7
2010	8	9
2015	10	11
pd.merge(df1, df2, left_on=['도시', '연도'], right_index=True)
도시	연도	인구	데이터1	데이터2
0	서울	2000	9853972	4	5
1	서울	2005	9762546	6	7
2	서울	2010	9631482	8	9
3	부산	2000	3655437	0	1
4	부산	2005	3512547	2	3

02. 두번째 방법

pd.merge(df1, df2.reset_index(), left_on=['도시', '연도'], right_on=['level_0', 'level_1'])
도시	연도	인구	level_0	level_1	데이터1	데이터2
0	서울	2000	9853972	서울	2000	4	5
1	서울	2005	9762546	서울	2005	6	7
2	서울	2010	9631482	서울	2010	8	9
3	부산	2000	3655437	부산	2000	0	1
4	부산	2005	3512547	부산	2005	2	3

join을 통한 합성

# pd.merge(left, right, ...) # on? index?... how?
# df1 -> left
df1 = pd.DataFrame({
    '품종': ['setosa', 'setosa', 'virginica', 'virginica'],
    '꽃잎길이': [1.4, 1.3, 1.5, 1.3]},
    columns=['품종', '꽃잎길이'])
df2 = pd.DataFrame({
    '품종': ['setosa', 'virginica', 'virginica', 'versicolor'],
    '꽃잎너비': [0.4, 0.3, 0.5, 0.3]},
    columns=['품종', '꽃잎너비'])
df1
품종	꽃잎길이
0	setosa	1.4
1	setosa	1.3
2	virginica	1.5
3	virginica	1.3
df2
품종	꽃잎길이
0	setosa	1.4
1	setosa	1.3
2	virginica	1.5
3	virginica	1.3
# join : 두 개의 df을 인덱스 기준으로 합쳐주는 메소드
df1.join(df2, lsuffix='l', rsuffix='r') # join -> index를 기준으로 합쳐버림
품종l	꽃잎길이	품종r	꽃잎너비
0	setosa	1.4	setosa	0.4
1	setosa	1.3	virginica	0.3
2	virginica	1.5	virginica	0.5
3	virginica	1.3	versicolor	0.3

merge

  • 두 데이터프레임 사이의 크기가 같을 필요가 없음 (기준이 되는 열, 인덱스를 바탕으로 outer, inner... 내용들을 재구성
  • on ... -> 어떠한 열을 기준으로 해줄까? index...
  • 두 개의 데이터가 공통 분모만 있다면 (키) 연결
  • 열 기준으로 연결할 필요가 없다? join -> 인덱스를 기준

concat

  • merge : 특정한 열을 기준(또는 인덱스)으로 해서 연결
  • concat : 기준 열을 사용하지 않고 데이터를 연결(붙임) - np.concatenate, vstack, hstack...
s1 = pd.Series([0, 1], index=['A', 'B'])
s2 = pd.Series([2, 3, 4], index=['A', 'B', 'C'])
# pd.concat
pd.concat([s1, s2], axis=0)
A    0
B    1
A    2
B    3
C    4
dtype: int64

피봇테이블과 그룹 분석

피봇테이블

  • Pivot Table : 데이터 열 중에서 두 개의 열을 각각 행과 열 인덱스로 사용해서 데이터를 조회해 놓은 것
  • 엑셀 -> 피봇테이블
  • Pandas -> 피봇테이블 pivot (행 인덱스로 사용할 열이름, 열 인덱스로 사용할 열 이름)
data = {
    "도시": ["서울", "서울", "서울", "부산", "부산", "부산", "인천", "인천"],
    "연도": ["2015", "2010", "2005", "2015", "2010", "2005", "2015", "2010"],
    "인구": [9904312, 9631482, 9762546, 3448737, 3393191, 3512547, 2890451, 263203],
    "지역": ["수도권", "수도권", "수도권", "경상권", "경상권", "경상권", "수도권", "수도권"]
}
columns = ["도시", "연도", "인구", "지역"]
df1 = pd.DataFrame(data, columns=columns)
df1
    도시	 연도	    인구	 지역
0	서울	2015	9904312	수도권
1	서울	2010	9631482	수도권
2	서울	2005	9762546	수도권
3	부산	2015	3448737	경상권
4	부산	2010	3393191	경상권
5	부산	2005	3512547	경상권
6	인천	2015	2890451	수도권
7	인천	2010	263203	수도권
df1.pivot(index=['도시'], columns=['연도'], values=['인구'])
     인구
연도	2005	2010	2015
도시			
부산	3512547.0	3393191.0	3448737.0
서울	9762546.0	9631482.0	9904312.0
인천	NaN	263203.0	2890451.0

그룹분석

  • 조건에 맞는 데이터가 하나 이상일 경우에 -> 데이터 그룹을 이룸 (피봇 테이블 형태로 표현을 X)
  • 그룹의 특성을 보여주는 (통계치, 계산...) => 그룹 분석 (group analysis)
  • group -> groupby
  1. 분석하고자 하는 Series, df에 groupby 메소드 호출 -> 그룹화
  2. 그룹화 -> 그룹 객체 -> 그룹 연산

groupby 메소드

  • 데이터를 그룹별로 분류하는 역할.
    • 열 또는 열의 리스트 (어떤 열을 기준으로 그룹을 넣어줄 것이냐
    • 행 인덱스
      => GroupBy (그룹화) => 그룹 함수 or 그룹 연산 => 특정한 값. 배열...
np.random.seed(0)
df2 = pd.DataFrame({
    'key1': ['A', 'A', 'B', 'B', 'A'],
    'key2': ['one', 'two', 'one', 'two', 'one'],
    'data1': [1, 2, 3, 4, 5],
    'data2': [10, 20, 30, 40, 50]
})
df2
	key1    key2	data1	data2
0	A	     one	1	10
1	A	    two	    2	20
2	B	    one	    3	30
3	B	    two	    4	40
4	A	    one	    5	50
# groupby.groups(속성) : 그룹별 구성 현황
groups = df2.groupby(df2['key1']) # 특정한 열
groups.groups
{'A': [0, 1, 4], 'B': [2, 3]}
# 평균
groups.mean()
# 중앙값 (median)
groups.median()
# 최대값
groups.max()
# 최소값
groups.min()
# 합계
groups.sum()
# 일괄적으로 곱함 / # 누적 수익률
groups.prod()
# 표준편차, 분산, 중간값(50%)
groups.std(), groups.var(), groups.quantile(0.5)

agg (aggregate)

0개의 댓글