[내일배움캠프] 23일 차 - 파이썬 개인 과제 리뷰
파이썬 개인 과제
문제 1
숫자 리스트의 평균 계산하기
최종 답안
numbers = [10, 20, 30, 40, 50]
def calculate_stock(numbers):
avg = sum(numbers) / len(numbers)
return avg
문제 2
계산기 만들기
- 함수명: simple_calculator
- num1 , num2 : 숫자 입력 값
- operator : 문자열 형태의 사칙 연산자 (+, -, * , /)
- 나누려는 숫자 num2 가 0인 경우 다음 문자를 반환 “Cannot divide by zero”
최종 답안
def simple_calculator(num1, num2, operator):
if operator == "+":
return num1 + num2
elif operator == "-":
return num1 - num2
elif operator == "*":
return num1 * num2
elif operator == "/":
if num2 == 0:
return "Cannot divide by zero"
else:
return num1 / num2
else:
return "Operator not supported"
문제 3
가장 큰 값 구하기
최종 답안
sales_data = {"apple": 50, "orange": 2, "banana" : 30}
def find_top_seller(sales_data):
max_sales = max(sales_data.values())
for keys in sales_data:
if sales_data[keys] == max_sales:
top_product = keys
return top_product, max_sales
참고 답안
sales_data = {"apple": 50, "orange": 2, "banana" : 30}
def find_top_seller(sales_data):
max_sales = -1 # 초기화하기 위해 존재할 수 없는 값 설정
top_product = ''
for key, value in sales_data.items():
if value > max_sales:
max_sales = value
top_product = key
return top_product, max_sales
새롭게 알게 된 것
괄호 없이 튜플 각각의 값만 얻는 법
sales_data = {"apple": 50, "orange": 2, "banana" : 30}
for key, value in sales_data.items():
print(key) # apple
print(value) # 50
print(key, value) # apple 50
문제 4
처음 답안 (틀림)
input_string = "abracadabra123321"
def remove_duplicates_and_count(input_string):
result_with_frequency = []
element = {}
l = list(input_string)
for i in l:
element[i] = l.count(i)
l.remove(i)
for j in element:
result_with_frequency += tuple(j.items())
return result_with_frequency
중간 답안 (틀림)
input_string = "abracadabra123321"
def remove_duplicates_and_count(input_strings):
result_with_frequency = []
element = {}
l = list(input_strings)
for i in l:
element[i] = l.count(i)
l = [x for x in l if x != i]
# 리스트 컴프리헨션: 불필요한 코드
# l(list) 자체를 바꿔버림, 맨 처음 반복문에서의 l와 두 번째 반복문의 l은 다름
for key, value in element.items():
result_with_frequency.append((key, value))
return result_with_frequency
최종 답안
input_string = "abracadabra123321"
def remove_duplicates_and_count(input_string):
result_with_frequency = []
element = {}
l = list(input_string)
for i in l:
element[i] = l.count(i)
for key, value in element.items():
result_with_frequency.append((key, value))
return result_with_frequency
참고 답안
input_string = "abracadabra123321"
def remove_duplicates_and_count(input_string):
frequency = {} # 자료의 빈도수를 넣을 딕셔너리 초기화
for char in input_string:
if char in frequency.keys():
frequency[char] += 1
else:
frequency[char] = 1
return list(frequency.items())
remove_duplicates_and_count(input_string)
틀린 이유
반복문 작동 방식을 제대로 이해하지 못해서 count가 제대로 집계되지 않음
- 아래와 같이 l의 원소 i를 차례대로 반복하도록 설계하고
for문 안에서 l을 다시 정의해
바뀐 l의 원소 i가 반복되는 문제
for i in l:
element[i] = l.count(i)
l = [x for x in l if x != i]
문제 5
이동 거리 구하기
처음 답안 (미완, 틀림)
player_positions = {
"John Doe": [(0, 0), (1, 1), (2, 2), (5, 5)],
"Jane Smith": [(2, 2), (3, 8), (6, 8)],
"Mike Brown": [(0, 0), (3, 4), (6, 8)]
}
def calculate_total_distances(player_positions):
records = []
jd = player_positions["John Doe"]
d = 0
for i in range (len(jd)-1):
d += ((jd[i][0]-jd[i+1][0])**2 + (jd[i][1]-jd[i+1][1])**2)**1/2 # 1/2승을 어떻게 처리해야 할까?
d = round(d, 2)
records.append(("John Doe", d))
return records
calculate_total_distances(player_positions)
중간 답안 (틀림)
player_positions = {
"John Doe": [(0, 0), (1, 1), (2, 2), (5, 5)],
"Jane Smith": [(2, 2), (3, 8), (6, 8)],
"Mike Brown": [(0, 0), (3, 4), (6, 8)]
}
def calculate_total_distances(player_positions):
records = []
jd = player_positions["John Doe"]
d1 = 0
for i in range (len(jd)-1):
d1 += ((jd[i][0]-jd[i+1][0])**2 + (jd[i][1]-jd[i+1][1])**2)**(1/2)
records.append(("John Doe", round(d1, 2)))
js = player_positions["Jane Smith"]
d2 = 0
for i in range (len(js)-1):
d2 += ((js[i][0]-js[i+1][0])**2 + (js[i][1]-js[i+1][1])**2)**(1/2)
records.append(("Jane Smith", round(d2, 2)))
mb = player_positions["Mike Brown"]
d3 = 0
for i in range (len(mb)-1):
d3 += ((mb[i][0]-mb[i+1][0])**2 + (mb[i][1]-jd[i+1][1])**2)**(1/2) # 코드 복붙하다가 놓친 부분!
records.append(("Mike Brown", round(d3, 2)))
return records
calculate_total_distances(player_positions)
최종 답안
player_positions = {
"John Doe": [(0, 0), (1, 1), (2, 2), (5, 5)],
"Jane Smith": [(2, 2), (3, 8), (6, 8)],
"Mike Brown": [(0, 0), (3, 4), (6, 8)]
}
def calculate_total_distances(player_positions):
records = []
for key, value in player_positions.items():
d = 0
for i in range (len(value)-1):
d += ((value[i][0]-value[i+1][0])**2 + (value[i][1]-value[i+1][1])**2)**(1/2)
records.append((key, round(d, 2)))
return records
참고 답안
player_positions = {
"John Doe": [(0, 0), (1, 1), (2, 2), (5, 5)],
"Jane Smith": [(2, 2), (3, 8), (6, 8)],
"Mike Brown": [(0, 0), (3, 4), (6, 8)]
}
def calculate_total_distances(player_positions):
records = []
for player, positions in player_positions.items(): # 사람 별 반복문
total_distance = 0.0 # 값이 소수점이므로 소수점으로 초기화!
for i in range(len(positions)-1): # 한 사람의 거리 별 반복문
x1, y1 = positions[i] # 첫 번째 점
x2, y2 = positions[i+1] # 두 번째 점
distance = ((x2-x1)**2 + (y2-y1)**2)**0.5
total_distance += distance
records.append((player, round(total_distance, 2)))
return records
틀린 이유
1. 코드 복붙하다가 바꿔야 할 변수를 바꾸지 않음
2. 1/2승 구하는 식에서 연산자의 우선 순위 고려하지 않아서 의도대로 작동하지 않음
- 틀린 코드
√x = x ** 1/2 - 정확한 코드
√x = x ** (1/2)
개선점
1. 튜플 언패킹
2. d = 0 등으로 초기화 선언할 때, 이후에 더해질 값이 소수점 값이라면 d = 0.0으로 선언해서 명확하게 한다
문제 6
Github에 있는 데이터 불러오기
최종 답안
import pandas as pd
def get_csv(url):
df = pd.read_csv(url, sep = ';')
return df
체크할 사항
컬럼을 불러온 후, 각 컬럼의 데이터 타입을 파악하자!
- 특히 날짜에 주의!
문제 7
결측치 확인
최종 답안
import pandas as pd
def get_csv(url):
df = pd.read_csv(url, sep = ';')
return df
df = get_csv(url)
def get_missing(data):
return df.isnull().sum()
새롭게 알게 된 것
메서드 체이닝(Method Chaining)
- 메서드 실행 → 메서드의 결과에 대해 또 메서드 실행
- 예시: df.isnull().sum()
- df: 데이터프레임 (표 형태)
- df.isnull(): df에 대해 null이면 True, not null이면 False 담아서 새로운 데이터프레임 반환
- df.isnull().sum(): df.isnull()의 결과인 데이터프레임에 대해 1(True)인 값만 합산
판다스에서 True는 1, False는 0
문제 8
조건에 맞는 데이터 출력하기
최종 답안
import pandas as pd
df = get_csv(url)
def get_price(df):
data = df.set_index('Destination')
result = data.groupby(level=0).agg(
mean = ('Price', 'mean'),
median = ('Price', 'median')
)
result['mean'] = result['mean'].round(1)
result['median'] = result['median'].round(1)
return result
참고 답안
import pandas as pd
df = get_csv(url)
def get_price(df):
return df.groupby('Destination')['Price'].agg(['mean', 'median']).round(1)
문제 9
수요일에 예약된 비행기 표 값 평균 구하기
최종 답안
import pandas as pd
df = get_csv(url)
def get_wed_price(df):
df['Date_of_Journey'] = pd.to_datetime(df['Date_of_Journey'], dayfirst=True)
df['num_day'] = df['Date_of_Journey'].dt.dayofweek
wed = df[df['num_day'] == 2]
mean_wed = round(wed['Price'].mean(), 2)
return mean_wed
참고 답안
def get_wed_price(df):
df['Date_of_Journey'] = pd.to_datetime(df['Date_of_Journey'], format ='%D-%m-%Y')
# 요일 컬럼 추가
df['Day_of_Week'] = df['Date_of_Journey'].dt.day_name()
# 수요일에 예약된 항공권의 평균 가격 계산
wednesday_avg_price = df[df['Day_of_Week'] == 'Wednesday']['Price'].mean()
# 불리언 인덱싱
return wednesday_avg_price.round(1)
새롭게 알게 된 것
컴퓨터에는 기본적으로 날짜를 넣어주면 무슨 요일인지 알려주는 시스템이 있다!
- 이 문제의 Date_of_Journey 컬럼은 문자열이라 날짜를 넣어도 무슨 요일인지 알려주지 않음
따라서 문자열에서 날짜형으로 바꿔야 한다! - 날짜형 자료 중에 요일 반환해주는 메서드 찾기!
- 날짜형 자료 중에서도 맨 처음 오는 것이 무엇인지 알아야 한다! 일이 먼저인지, 월이 먼저인지, 연도가 먼저인지
참고 자료
문제 10
출발 시간 기준 비행기 수 집계하기
중간 답안
import pandas as pd
def get_csv(url):
df = pd.read_csv(url, sep = ';')
return df
df = get_csv(url)
def get_cat(df):
df['Time_Of_Day'] = df['Dep_Time'].apply(lambda x: '아침' if '05:00' <= x < '12:00' else
('오후' if '12:00' <= x < '18:00' else
('저녁' if '18:00' <= x < '24:00' else '밤')))
grouped_count = df.groupby('Time_Of_Day')['Airline'].count()
new_df = grouped_count.reset_index()
new_df = new_df.sort_values(by='Airline', ascending=False)
return new_df
최종 답안
import pandas as pd
from datetime import time
def get_cat(df):
df['time_seg'] = pd.to_datetime(df['Dep_Time'], format='%H:%M').dt.time
df['Time_Of_Day'] = df['time_seg'].apply(lambda x: '아침' if time(5, 0) <= x < time(12, 0) else
('오후' if time(12, 0) <= x < time(18, 0) else
('저녁' if time(18, 0) <= x <= time(23, 59) else '밤')))
grouped_count = df.groupby('Time_Of_Day')['Airline'].count()
new_df = grouped_count.reset_index()
new_df = new_df.sort_values(by='Airline', ascending=False)
new_df = new_df.reset_index(drop=True)
return new_df
참고 답안
def get_cat(df):
df['Dep_Time'] = pd.to_datetime(df['Dep_Time'], format='%H:%M')
# 출발 시간을 기준으로 "아침", "오후", "저녁", "밤"으로 분류하는 lambda 함수 적용
df['Time_Of_Day'] = df['Dep_Time'].apply(
lambda x: '아침' if 5 <= x.hour < 12 else
'오후' if 12 <= x.hour < 18 else
'저녁' if 18 <= x.hour < 24 else
'밤'
)
# 분류 결과 확인
return df.groupby(['Time_Of_Day'])[['Airline']].count().sort_values(by='Airline', ascending= False).reset_index()
get_cat(df)
틀린 이유
판다스 메서드 쓸 때, 메서드 결과를 할당하지 않아 코드 결과가 그냥 사라짐
- 파이썬에서 할당이 필요한 메서드와 할당 필요 없는 메서드 구분하는 것 중요하다
- 할당 필요없음: list의 append()
- 할당 필요함: 판다스 대부분