데이터프레임의 합성
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 로 연결
| 주소 | 지원금 |
|---|
| 서울시 | 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
- 분석하고자 하는 Series, df에
groupby 메소드 호출 -> 그룹화
- 그룹화 -> 그룹 객체 -> 그룹 연산
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)