apply()
를 이용하면 함수를 이용하여 데이터 프레임에 값을 적용할 수 있습니다
일정한 동작으로 데이터 프레임을 수정하고자 할 때 편리하게 이용할 수 있는 기능입니다.
지시사항
데이터 프레임 df
에는 정수를 담고있는 Num
칼럼이 있습니다.
df
데이터 프레임에 함수를 이용하여 Num
의 제곱수를 나타내는 칼럼인 Square
칼럼을 추가하고, 데이터프레임을 출력해봅시다.
Q1.
값을 받으면 제곱을 해서 돌려주는 함수를 만들어 봅시다.
def square(x):
return x**2
df["Square"] = df["Num"].apply(square)
df
Q2.
함수 대신 람다 표현식으로도 적용하실 수 있습니다.
df["square"] =df["Num"].apply(lambda x: x**2)
groupby()
함수를 이용하면 키 값을 기준으로 그룹으로 묶을 수 있습니다.
groupby()
함수의 사용 예시를 들자면, 시험 성적 데이터에서 각 반을 그룹으로 묶어 각 반의 평균 점수를 구할 수 있습니다.
지시사항
Q1.
데이터 프레임의 key
칼럼을 groupby
함수로 묶고, key
별로 data1과 data2 합계를 출력해보세요.
import numpy as np
import pandas as pd
df = pd.DataFrame({
'key': ['A', 'B', 'C', 'A', 'B', 'C'],
'data1': [1, 2, 3, 1, 2, 3],
'data2': [4, 4, 6, 0, 6, 1]
})
print("DataFrame:")
print(df, "\n")
# key를 기준으로 묶어 합계
df.groupby("key").sum()
print(df.groupby("key").sum())
Q2.
데이터 프레임의 key
와 data1
칼럼을 groupby
함수로 묶고, key
와 data1
별로 data2
의 합계를 출력해보세요.
df.groupby(["key","data1"]).sum()
aggregate()
함수를 이용하여 키값을 기준으로 그룹으로 묶은 결과의 요약 통계량을 구해봅시다.
aggregate()
함수의 결과값 또한 데이터프레임으로 반환되어 한 눈에 보기 편리합니다.
지시사항
aggregate()
함수로 요약 통계량을 출력해보세요.
Tip
agregate 메소드에 함수를 매개변수로 넣어줄 때, min, max, mean, count 등의 특정 함수들은 문자열 형태로 넘겨주실 수 있습니다df.groupby('key').aggregate([min, np.median, max])
Q1.
데이터 프레임을 key
를 기준으로 묶고, key
별 data1
과 data2
각각의 최솟값과 중앙값, 최댓값을 출력해봅시다.
import numpy as np
import pandas as pd
df = pd.DataFrame({
'key': ['A', 'B', 'C', 'A', 'B', 'C'],
'data1': [0, 1, 2, 3, 4, 5],
'data2': [4, 4, 6, 0, 6, 1]
})
print("DataFrame:")
print(df, "\n")
# 데이터 프레임을 'key' 칼럼으로 묶고, data1과 data2 각각의 최솟값, 중앙값, 최댓값을 출력
df.groupby("key").aggregate([min,np.median,max])
Q2.
데이터 프레임을 key
를 기준으로 묶고, key
별 data1
의 최솟값과 data2
의 합계를 출력해봅시다.
df.groupby("key").aggregate({"data1":min, "data2":max})
그룹으로 묶은 값에
filter()
함수와apply()
함수를 적용하고, 설정한 조건으로 데이터 프레임에서 원하는 값만 추출할 수 있습니다.
지시사항
Q1.
filter 함수를 이용하여 key별로 그룹을 묶고, 그룹별 data2
평균이 3이 넘는 데이터만 출력해봅시다.
import numpy as np
import pandas as pd
df = pd.DataFrame({
'key': ['A', 'B', 'C', 'A', 'B', 'C'],
'data1': [0, 1, 2, 3, 4, 5],
'data2': [4, 4, 6, 0, 6, 1]
})
print("DataFrame:")
print(df, "\n")
# groupby()로 묶은 데이터에 filter를 적용.
# key별 data2의 평균이 3이 넘는 인덱스만 출력
print("filtering : ")
def filter_by_mean(x):
return x["data2"].mean() > 3
print(df.groupby("key").filter(filter_by_mean))
Q2.
apply 함수와 람다식을 이용해서, key를 기준으로 묶은 그룹별 data1
과 data2
변수의 최댓값에서 최솟값을 뺀 값을 출력해보세요.
print("applying : ")
df.groupby("key").apply(lambda x: x.max()-x.min())
인덱스를 계층적으로 만드는 방법 Multi Index에 대해 알아봅시다.
또한, 데이터에서 필요한 데이터만 뽑아서 새롭게 요약 분석할 수 있는 Pivot Table에 대해서도 알아봅시다.
import numpy as np
import pandas as pd
df1 = pd.DataFrame(
np.random.randn(4, 2),
index=[['A', 'A', 'B', 'B'], [1, 2, 1, 2]],
columns=['data1', 'data2']
)
print("DataFrame1")
print(df1, "\n")
df2 = pd.DataFrame(
np.random.randn(4, 4),
columns=[["A", "A", "B", "B"], ["1", "2", "1", "2"]]
)
print("DataFrame2")
print(df2, "\n")
# 명시적 인덱싱을 활용한 df1의 인덱스 출력
print("df1.loc['A', 1]")
print(df1.loc['A', 1], "\n")
# df2의 [A][1] 칼럼 출력
print('df2["A"]["1"]')
print(df2["A"]["1"], "\n")
데이터를 시각화하기 위해 Matplotlib에 대해서 알아봅시다.
Matplotlib은 막대 그래프, 산점도 등 데이터 시각화 기능을 가진 대표적인 파이썬 라이브러리입니다.
앞에서 배운 numpy, pandas에서 처리한 데이터를 한 번 그래프로 그려봅시다.
x = [1, 2, 3, 4, 5]
y = [1, 2, 3, 4, 5]
fig, ax = plt.subplots()
ax.plot(x, y)
ax.set_title("First Plot")
ax.set_xlabel("x")
ax.set_ylabel("y")
Tip!
subplots는 1개의 figure와 1개 이상의 그래프(ax)를 생성할 수 있습니다.
figure는 그래프를 그리는 도화지같은 개념입니다.
옵션을 지정함에 따라, 1개의 figure에 2개 이상의 그래프를 같이 그릴 수도 있습니다.
import matplotlib.pyplot as plt
x = [1, 2, 3, 4, 5]
y = [1, 2, 3, 4, 5]
# 그래프를 1개 그리는 코드 작성
plt.plot(x,y)
plt.title("Graph")
plt.xlabel("x축")
plt.ylabel("y축",rotation='horizontal')
#그래프를 여러개 그리는 코드 작성(matplotlib를 API처럼 사용할때)
fig, ax = plt.subplots(1,2, figsize=(12,6)
#fig -> 전체 그래프에 대한 속성
#ax -> 각 개별 그래프 : ax[0] ax[1] 등 지정해서 속성 수정 가능
matplotlib으로 그릴 수 있는 여러가지 그래프 중 선 그래프(Line Graph)를 직접 그려봅시다.
속성(linestyle, marker, color) 값을 변경하여 그래프를 그리는 다양한 방법에 대해서 알아봅시다.
자주 사용되는 옵션은 아래와 같습니다.
Line Styles
기호 | 의미 |
---|---|
- | 실선 |
-- | 대시 선 |
-. | 대시 점 선 |
: | 점선 |
Markers
기호 | 의미 | 기호 | 의미 |
---|---|---|---|
. | 점 | , | 픽셀 |
o | 원 | s | 사각형 |
v, <, ^, > | 삼각형 | 1, 2, 3, 4 | 삼각선 |
p | 오각형 | H, h | 육각형 |
예시
ax.plot 함수의 marker, color, linestyle 의 옵션을 변경하실 수 있습니다.
x = np.arange(10)
fig, ax = plt.subplots()
ax.plot(
x, x, label='y=x',
marker='o',
color='blue',
linestyle=':'
)
ax.plot(
x, x**2, label='y=x^2',
marker='^',
color='red',
linestyle='--'
)
ax.set_xlabel("x")
ax.set_ylabel("y")
ax.legend(
loc='upper left',
shadow=True,
fancybox=True,
borderpad=2
)
plt.show()
Tip!
예시 코드에서 figure와 ax가 각각 1개인데, ax.plot 함수를 두 번 호출했죠?
이렇게 하나의 ax에 여러 번 그래프를 그리면, 그래프를 겹쳐서 그릴 수 있습니다.
import numpy as np
import matplotlib.pyplot as plt
Scatter 그래프는 산점도라고도 하는데, 이를 사용하게 되면 값 사이의 관계를 파악하기 용이해지고 데이터 셋에서 이상값을 찾기도 용이합니다.
둘 이상의 측정값의 상관 관계를 파악하고 시각화 할 수 있는 훌륭한 그래프 입니다.
x = np.random.randn(50)
y = np.random.randn(50)
colors = np.random.randint(0, 100, 50)
sizes = 500 * np.pi * np.random.rand(50) ** 2
```python
ax.scatter(
x, y, c = colors, s = sizes
)
Tip!
예시 코드에서는 colors와 sizes가 무작위 값으로 설정되었지만, 실제로 데이터 분석을 지정할 때에는 데이터의 성향에 따라 색을 구분해 줄 수 있고, 데이터의 크기에 따라 점의 크기를 조절할 수 있습니다.
- 변수의 값 뿐만 아니라, 색깔과 크기를 적절히 조절하면 시각화를 하는 의도를 효과적으로 나타낼 수 있습니다.
import numpy as np
import matplotlib.pyplot as plt
x = np.random.randn(50)
y = np.random.randn(50)
colors = np.random.randint(0, 100, 50) #50개의 랜덤한 color변수 지정
sizes = 500 * np.pi * np.random.rand(50) ** 2 # 50개의 랜덤한 사이즈 *3.14 * 500
fig ,ax = plt.subplots()
ax.scatter(x, y, c = colors, s = sizes, alpha=0.2)
plt.show()
- 우리가 잘알고 있는 Bar그래프(막대형 차트)는 여러 값을 비교하는데 적합합니다. 여러개의 값을 입력 받고 그 값들을 한눈에 비교 할 수 있습니다.
- Histogram은 일정 시간 동안의 숫자 데이터 분포를 시각화 하는데 적합합니다.
x와 y 데이터는 각 스포츠의 종목과, 선호하는 학생의 수를 조사한 결과입니다.
x와 y 데이터로 막대 그래프를 그립니다.
z
데이터는 1000개의 정규분포 난수를 담고 있습니다.
z
데이터를 등급을 50개로 나눈 히스토그램으로 출력해봅니다.
Tip!
fig, axes = plt.subplots(1, 2, figsize=(8, 4))
이 코드는, 하나의 도화지(figure)에
1*2
의 모양으로 그래프를 그리도록 합니다.
그래프를 2개 그리고, 가로로 배치한다는 의미입니다.
axes[0]
은 막대 그래프를,axes[1]
은 히스토그램을 그립니다.
Tip 2!
matplotlib 의 pyplot으로 그래프를 그릴 때, 기본 폰트는 한글을 지원하지 않습니다.
한글 지원 폰트로 직접 바꾸어주면 한글을 사용하실 수 있습니다.
아래는 한글을 지원하는 코드입니다.import matplotlib.pyplot as plt plt.rc('font', family='Malgun Gothic') # For windows plt.rc('font', family='AppleGothic') # For MacO
위 코드 덕분에, 막대 그래프에서 축구, 야구, 농구, 배드민턴, 탁구가 올바르게 출력되었습니다.
import matplotlib.font_manager as fm
font_list = [f.name for f in fm.fontManager.ttflist]
print(font_list)
import matplotlib.pyplot as plt
# plt.rc('font', family='Malgun Gothic') # For windows
plt.rc('font', family='AppleGothic') # For MacO
x = np.array(["축구", "야구", "농구", "배드민턴", "탁구"])
y = np.array([18, 7, 12, 10, 8])
z = np.random.randn(1000)
fig, axes = plt.subplots(1, 2, figsize=(8, 4))
# Bar 그래프
axes[0].bar(x, y)
# 히스토그램
axes[1].hist(z, bins = 50)
plt.show()
Pandas를 이용해 csv 파일을 불러와 시각화를 진행해보도록 하겠습니다.
포켓몬에 대한 데이터가 담긴 csv 파일을 불러와서 공격 타입에 따라 그래프를 그리고 라벨을 한번 붙여보도록 합시다.
공격 능력치와 수비 능력치가 x와 y축으로 주어지고, 물 속성 포켓몬은 파란색, 불 속성 포켓몬은 빨간색으로 표현한 모습입니다.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_csv("pokemon.csv")
df.head(3)
하나의 그래프에 두 scatter로 시각화하기
fire = df[
(df['Type 1']=='Fire') | ((df['Type 2'])=="Fire")
]
water = df[
(df['Type 1']=='Water') | ((df['Type 2'])=="Water")
]
fig, ax = plt.subplots()
ax.scatter(fire['Attack'], fire['Defense'], color='red', label='Fire', marker="*", s=50)
ax.scatter(water['Attack'], water['Defense'], color='blue', label="Water", s=25)
ax.set_xlabel("Attack")
ax.set_ylabel("Defense")
ax.legend(loc="upper right")
plt.show()
subplots로 여러개의 그래프로 나눠서 시각화하기
fig,ax = plt.subplots(1,2, figsize=(12,6))
ax[0].scatter(fire['Attack'], fire['Defense'], color='red', label='Fire', marker="*", s=50)
ax[1].scatter(water['Attack'], water['Defense'], color='blue', label="Water", s=25)
fig.suptitle("Fire and Water")
# ax[0].set_xlabel("Attack")
# ax.set_ylabel("Defense")
ax[0].set_title("fire")
ax[1].set_title("water")
ax[1].legend(loc="upper left")
ax[0].legend(loc="upper left")
fig.tight_layout #라벨 간격 조정하기
plt.show()
번외 - 포켓몬 데이터의 컬럼 이름들을 바꿔보자.
new_name=[] for name in df.columns: #Column명에 공백과 _(언더바)를 바꾸기 new_name.append(name.replace(" ","-").replace("_","")) df.columns=new_name df.columns > list comprehension #리스트표현식으로 압축 df.columns=[name.replace(" ","-").replace("_","") for name in df.columns] df.columns
파이썬의 가장 큰 장점 중 하나는 간결한 코드입니다.
for
문을 리스트 안에 입력하면 새로운 리스트를 코드 한 줄로 간결하게 생성할 수 있습니다. 아래의 두 코드는 동일하게 작동합니다.nums = [1, 2, 3] new_nums = [n + 1 for n in nums]
nums = [1, 2, 3] new_nums = [] for n in nums: new_nums.append(n + 1)
for
와if
를 함께 사용하면 리스트의 특정 원소만 선택하여 리스트에 추가할 수도 있습니다.nums = [1, 2, 3, 4] even_nums = [n for n in nums if n % 2 == 0]
데이터 분석에 응용하기
단어 모음 words
에서 prefix
로 시작하는 단어로만 이루어진 리스트를 리턴하는 filter_by_prefix
함수를 완성하세요.
words = [
'apple',
'banana',
'alpha',
'bravo',
'cherry',
'charlie',
]
def filter_by_prefix(words, prefix):
prefix_list= [ word for word in words if word.startswith(prefix)==True]
return prefix_list
a_words = filter_by_prefix(words, 'a')
print(a_words)
#리스트 표현식으로
a_words_com = [word for word in words if word.startswith("a")==True]
a_words_com
sorted()
를 활용하면 리스트를 특정 기준에 맞춰 정렬할 수 있습니다. 이때 기준은key
에 저장한 함수를 따르게 됩니다.
- 아래의 코드는 숫자의 리스트를 절댓값을 기준으로 정렬합니다. 여기서
abs()
함수는 절댓값을 리턴하는 파이썬 내장 함수입니다.new_nums = sorted([-4, 1, -3], key=abs) print(new_nums) [1, -3, -4]
데이터 분석에 응용하기
단어의 사용 빈도를 쉽게 확인하기 위해서는 단어를 빈도 순서대로 정렬하는 함수 get_freq()
와 sort_by_frequency()
함수를 만들어봅시다
pairs = [
('time', 8),
('the', 15),
('turbo', 1),
]
#(단어, 빈도수) 쌍으로 이루어진 튜플을 받아, 빈도수를 리턴합니다.
def get_freq(pair):
return pair[1]
#(단어, 빈도수) 꼴 튜플의 리스트를 받아, 빈도수가 낮은 순서대로 정렬하여 리턴합니다.
def sort_by_frequency(pairs):
return sorted(pairs, key=get_freq)
print(sort_by_frequency(pairs))
데이터프레임의 컬럼 이름을 사용하면 특정 칼럼을 조회할 수 있습니다.
컬럼 하나를 선택할 경우, pandas의 Series형태로 반환됩니다.
예시
학생의 이름, 국어, 수학, 영어 성적을 입력으로 받고, 이를 저장한 데이터프레임 df 에서 국어 컬럼을 조회해 출력해 보세요.
입력 예시3 홍길동 80 70 80 박철수 60 70 80 김영희 70 90 80
import pandas as pd
total_student = int(input('총 성적의 개수 : '))
col_names = ['이름', '국어', '수학', '영어']
scores = [[int(col) if col.isdigit() else col for col in input().split()] for _ in range(total_student)]
df = pd.DataFrame(scores, columns=col_names)
print('\n', df, '\n')
데이터프레임에 값을 지정해주어 새로운 컬럼을 추가할 수 있습니다.
예시
위에서 활용 df를 활용하여, 학생별 사회 성적이 담긴 new_score
리스트를 활용하여 사회 열을 추가한 후, df
를 출력해 보세요.
입력 예시
3 홍길동 80 70 80 박철수 60 70 80 김영희 70 90 80 50 60 60
실행 결과
이름 국어 수학 영어 사회 0 홍길동 80 70 80 50 1 박철수 60 70 80 60 2 김영희 70 90 80 60
import pandas as pd
total_student = int(input('총 성적의 개수 : '))
col_names = ['이름', '국어', '수학', '영어']
scores = [[int(col) if col.isdigit() else col for col in input().split()] for _ in range(total_student)]
new_score = list(map(int, input().split()))
df = pd.DataFrame(scores, columns=col_names)
df["사회"]= new_score #리스트를 새로운 칼럼에 리턴하여 칼럼 생성
print('\n', df, '\n')
print('new_score :', new_score, '\n')
2023년 서울시의 지역, 연령별 인구수 데이터를 활용하여 지역구별 고령화 정도를 분석해봅니다.
아래 지시사항을 따라 데이터를 가공하는 수행하세요.
df
에 저장되어 있습니다.df
에 “노인인구비율”컬럼을 생성하여 지역구별로 총인구수 대비 노인인구의 비율을 저장합니다. (70대 이상의 인구를 노인 인구라고 가정합니다)df
에 “고령여부”컬럼을 생성하고 “노인인구비율” 컬럼값이 0.14 이상이면 O
(대문자 o), 0.14 미만이면 X
(대문자 x)를 저장합니다.df = pd.read_csv("seoul_population.csv")
df.head(3)
df["노인인구비율"] = (df["70대"]+df["80대"]+df["90대 이상"]) / df["총인구수"]
df['고령여부']=df["노인인구비율"].apply(lambda x: "O" if x >= 0.14 else "X")
df.head(10)
딕셔너리를 이용하면 데이터프레임의 특정 컬럼의 값을 변경할 수 있습니다.
숫자로 된 컬럼을 대상으로 데이터를 해석할 수 있도록 변환하고 몇 개로 구성되어 있는지 확인해보겠습니다.
[데이터 소개]
health_check.csv
에는 성인 1만명의 건강검진 데이터이며 데이터는 다음과 같이 구성되어 있습니다.
컬럼 명 | 데이터 소개 |
---|---|
BTH_G | 연령(그룹) |
SBP | 수축기 혈압 |
DBP | 연령(그룹) |
FBS | 공복 혈당 |
SEX | 성별 |
DIS | 고혈압/당뇨병 진료 여부 |
BMI | 체질량 지수 |
데이터프레임 df
의 SEX 컬럼에 숫자로 된 데이터를 변환합니다.
데이터프레임 df
의 DIS 컬럼에 숫자로 된 데이터를 변환합니다. (문자, 띄어쓰기가 안내된 사항과 다르면 채점이 정상적으로 작동하지 않습니다)
df
의 DIS 컬럼에 값들이 몇 개씩 저장되어 있는지 확인합니다.import pandas as pd
df = pd.read_csv('health_check.csv')
sex = {
1: "남성",
2: "여성"
}
#. Series.map() 활용
df['SEX'] = df['SEX'].map(sex)
dis = {
1: "고혈압/당뇨병 진료내역 있음",
2: "고혈압 진료내역 있음",
3: "당뇨병 진료 내역 있음",
4: "고혈압/당뇨병 진료내역 없음"
}
df['DIS'] = df['DIS'].map(dis)
dis_count = df["DIS"].value_counts()
print(dis_count)
모든 데이터는 우리가 분석하기 편한 형태로 존재하고 있지 않습니다.
특히, 숫자 데이터는 콤마를 포함하는 경우가 있습니다.
ex) 1234 → 1,234
이럴 경우 컴퓨터는 콤마로 인해 문자열 자료형(object)로 인식하게 됩니다.
콤마가 있는 숫자에서 콤마를 제거하여 숫자형(int)으로 변경하는 실습을 진행하겠습니다.
[데이터 소개]
access_data.csv
에는 한 홈페이지의 접속경로 통계 데이터가 저장되어 있습니다.
컬럼 명 | 데이터 소개 | 데이터 유형 |
---|---|---|
접속일자 | 접속한 날짜 | object |
PC접속수 | PC를 통해 홈페이지에 접속한 수 | object |
모바일접속수 | 모바일을 통해 홈페이지에 접속한 수 | object |
df = pd.read_csv("access_data.csv")
print(df.info())
print("===================\n")
print(df.head())
df["접속일자"] = pd.to_datetime(df['접속일자'])
def del_comma(data: str):
"문자열 data에 콤마(,)가 있다면 제거하는 함수"
if "," in data:
data = data.replace(",", "")
return data
df["PC접속수"] = None
df["모바일접속수"] = None
df["PC접속수"] = None
df["모바일접속수"] = None
df["전체접속수"] = None
print(df.info())
print("===================\n")
print(df.head())