[TIL#21 250318] 잠이 쏟아진다....

강민지·2025년 3월 18일

데이터분석_TIL

목록 보기
21/81

Daily plan

🌞오전

- SQL 코드카타 82~85
- 10시 파이썬 라이브세션
- 라이브세션 정리

🔥 오후

- 데이터전처리&시각화 강의 3주차
- 파이썬 라이브세션 내용 정리 + 코드 복습
- 빅분기 정리 + 암기

🌝 저녁

- 알고리즘 코드카타 17~20
- 데일리 스크럼 + TIL 제출

SQL 코드카타

Q82 - Recplace Employee ID With The Unique Identifier

select unique_id, e.name
from employees e
    left join employeeUNI euni 
    on e.id = euni.id

Q83 - Product Sales Analysis I

select p.product_name, s.year, s.price
from sales s 
    join product p
    on s.product_id = p.product_id

Q84 - Customer Who Visited but Did Not Make Any Transactions

select customer_id,
    count(customer_id) count_no_trans
from visits
where visit_id not in (select distinct visit_id from transactions)
group by customer_id

Q85 - Rising Temperature

여기서 한 번 막혔다,,

select w1.id
from weather w1
    left join weather w2
    on w1.id = w2.id+1
where w1.temperature > w2.temperature

그냥 self join으로 인덱스 하나씩 미뤄서 붙여버렸는데 출제자가 한 수 위였음...
테스트 중 일부는 날짜 순서를 뒤집어 놨다..ㅋㅋ

접근법이 도무지 안떠올라서 gpt한테 힌트 구걸한 뒤에 다시 풀어야지,,,


파이썬 개인 과제 해설

나의 풀이

  • 최댓값 찾는 알고리즘
numbers = [10,70,30,60,20]

max_n=0
for n in numbers:
	if n > max_n:
    	max_n = n
        
print(max_n)

3번 (max()를 사용하지 않고 위의 '최댓값 찾는 알고리즘'을 이용한 방법)

def find_top_seller(sales_data):
    max_value = 0
    for key, value in sales_data.items():
        if value > max_value:
            max_value = value
            max_key = key

    return max_key, max_value

print(find_top_seller(sales_data))

7번

for player, positions in player_positions.items():
	total_distance = 0.0
    for i in range(0, len(positions)-1):
    	x1 = positions[i][0]
        y1 = positions[i][1]
        x2 = positions[i+1][0]
        y2 = positions[i+1][1]
        distance = ((x2-x1)**2 + (y2-y1)**2)**0.5
        total_distance += distance
    print(f"{player}의 총 누적 이동 거리: {total_distance:.2f} 미터"}

나는 그냥 변수 설정없이 한줄로 계산식을 쭉 써버렸는데,,
확실히 좌표를 하나씩 변수로 정리하니까 보기에는 더 좋은 것 같다.

  • numpy.sqrt
    0.5를 제곱하는 대신 np.sqrt를 사용한 코드이다.
    np.sqrt 대신 math 라이브러리를 import해서 math.sqrt를 쓰는 방법도 있다.
import numpy as np

for player, positions in player_positions.items():
	total_distance = 0.0
    for i in range(0, len(positions)-1):
		x1, y1 = positions[i]
        x2, y2 = positions[i+1]
        distance = np.sqrt((x2-x1)**2 + (y2-y1)**2)
        total_distance += distance
	print(f"{player}의 총 누적 이동 거리: {total_distance:.2f} 미터")

8번

def solution(s):

  en_num = {'zero':0, 'one':1, 'two':2, 'three':3,'four':4, 'five':5, 'six':6, 'seven':7, 'eight':8, 'nine':9}

  ko_num = {'영':0, '일':1, '이':2, '삼':3, '사':4, '오':5, '육':6, '칠':7, '팔':8, '구':9}

  en_n = 0
  for item in en_num.items():
      word, num = item

      if word in s:
          en_n += 1
          split1, split2 = s.split(word)
          s = split1 + str(num) + split2

  ko_n = 0
  for item in ko_num.items():
      word, num = item

      if word in s:
          ko_n += 1
          split1, split2 = s.split(word)
          s = split1 + str(num) + split2

  return s, ko_n, en_n

en_num과 ko_num이라는 딕셔너리에 각 단어에 대응하는 숫자를 키-값으로 정리를 해준다.
그리고 for문으로 en_num 딕셔너리를 순회하며 각 단어(key)가 주어진 문자열 s에 포함되었는지 확인한다.
만약 단어가 s에 포함되어 있다면, 그 단어를 기준으로 s의 앞,뒤를 split1, split2로 분리하고 단어를 숫자로 바꾸어서 다시 붙여준다. (s = split1 + num + split2)
이러한 과정을 ko_num 딕셔너리로 한번 더 동일하게 처리한다.

split함수를 이용해서 word를 기준으로 앞,뒤를 분리해내는 방법이 있었다니....!


아티클

A/B테스트 제대로 이해하기(3)

  • 요약 :

  • 주요 포인트 :

    • AB Testguide라는 웹서비스를 통해 간단한 숫자 입력만으로 A/B 테스트를 계산한 결과를 얻을 수 있음
    • 계산기 세팅
      • Test data: 각 그룹의 표본 크기와 그룹별 최종 전환 숫자 → 실험을 통해 각 그룹에 모인 트래픽과 그 중 원하는 결과로 최종 전환된 트래픽을 직접 입력
      • Settings-hypthesis: 단측 검정 or 양측 검정 설정
      • Setting-confidence: 신뢰수준(%) 설정
    • 단측 검정 vs 양측 검정
      • 일반적으로 양측 검정이 더 보수적이고 안전한 접근임
      • 단측 검정에서 ‘차이가 유의미하지 않다’라는 결과가 나와도, 양측 검정에서는 ‘차이가 유의미하다’라고 나올 수 있음
    • 결과 해석
      • p-value에 따라 결과가 유의미한지 여부가 나타남 (significant/ not significant)
      • 실험 결과가 유의미하지 않다면 애초에 두 그룹에 별 차이가 없거나, 더 많은 데이터를 모아야 함 → 정말로 차이가 없는 건지, 표본이 부족해서 알 수 없는 건지에 대한 고민이 필요함
  • 인사이트 :

    실험을 세팅할 때 test data는 실제 트래픽 정보를 그대로 입력하는 것이므로 결과 해석에 영향을 주지 않는다. 신뢰 수준은 영향을 줄 수 있지만 보통 95%로 선택하기 때문에 큰 영향을 주지는 않는다. 하지만 단측/양측 검정 선택은 결과 해석이 완전히 달라질 수도 있을 만큼 큰 영향을 준다. 따라서 실험을 세팅할 때 실험 목적에 따라 전략적으로 선택할 필요가 있다.

    p-value가 유의미하지 않게 나타나도 바로 실험 실패로 결론을 내리는 것이 아니라 표본 수나 실험 디자인에 대해 다시 고민해 볼 필요가 있다. 애초에 실험 설계 단계에서부터 충분한 표본 수를 설정하는 것이 좋을 것 같다.


파이썬 라이브세션 4회차 이어서 정리

2. Pivot Table

  • pivot_table(): 데이터의 열을 기준으로 피벗테이블로 변환시키는 함수

  • 주요 옵션

    	- index: 인덱스로 사용될 열
    • columns: 열로 사용될 열
    • values: 값으로 사용될 열
    • aggfunc: 어떤 계산을 할지 (sum, mean, std, count, nunique, max, min)
    • fill_value: NaN 값을 처리하고 싶을 때 사용 (fill_value=0이 가장 많이 사용됨)
    • dropna: 결측치 삭제 여부 결정
    • sort: index or columns 기준 정렬
  • index나 columns에 리스트 형태를 입력하면 멀티 인덱스 기반 피벗테이블을 생성 가능

  • values에 리스트를 입력하면 각 값에 대한 테이블이 연속적으로 생성됨

  • 문법 예시

# Age라는 축을 기준으로 카테고리 별 고객 id 카운트
pd.pivot_table(df2, index='Age', columns='Category', values='Customer ID', aggfunc='count')

# Age, Category라는 축을 기준으로 성별에 따른 Previous Purchases 최솟값, 최댓값
pd.pivot_table(df2, index=['Age','Category'], columns='Gender', values='Previous Purchases', aggfunc=['min','max']

# 성별을 축으로, 사이즈와 나이별 고객 id 고유하게 카운트
pd.pivot_table(df2, index='Gender', columns=['Size','Age'], values='Customer ID", aggfunc='nunique')

3. 그 외 유용한 메서드

객체

  • 객체: 어떠한 속성값이나 행동(동작)을 일컫는 단위
  • 속성(변수, attribute)이나 메서드(함수, method)를 의미할 수 있음
    • 속성은 숫자, 문자 등의 정보를 의미
    • 메서드는 동작을 의미
  • 객체는 속성+메서드가 아닌, '속성이나 행동을 포함하는 단위'

함수 vs 메서드

  • 함수는 독립적인 속성을 가지고, 메서드는 객체에 종속적임
    • 특정 객체에 적용되는 함수를 메서드라고 함
  • 함수는 재사용이 가능하지만 메서드는 재사용이 어려움
  • 함수는 호출 객체가 없지만, 메서드는 호출 객체가 있음
  • 함수는 이름만으로 호출이 가능하고, 메서드는 대상이 되는 객체가 '.'으로 연결되어 있어야 함
    • 함수명(인자) ------------- ex) str(), int()
    • 객체.메서드명(인자) ----- ex) df.split(), df.append()

lambda

  • 람다 함수는 이름이 없는 함수
  • 일반적으로 함수를 한번만 사용하거나 함수를 인자로 전달해야 하는 경우에 유용
  • 문법 예시
## labmda 함수를 이용하여 홀수 출력

mylist = [1, 2, 3, 4, 5]

mylist2 = list(filter(lambda x: x%2==1, mylist))
print(my_list2)

## lambda 함수를 이용하여 정렬

mylist = ['apple', 'banana', 'cherry']

mylist2 = sorted(mylist, key=lambda x: len(x))
print(my_list2)

split

  • 하나의 값으로 묶여있는 데이터를 문자열 기준으로 나눌 때 사용

  • 특정 문자나 패턴으로 나눌 수 있음

  • 주요 옵션

    • sep: 문자열을 나눌 구분자 기입
    • maxsplit: 최대 split 횟수 (모두 나누는 게 디폴트)
  • 문법 예시

s = "aa.bb.cc.dd.ee.ff.gg"
### '.' 구분자 기준으로 분할
s.split('.')
s.split(sep='.')  # 두 코드의 결과는 동일

### '.' 구분자 기준 데이터 분할 후 컬럼으로 받음
# lambda 함수와 결합하여 사용하는 경우
df2['x'] = "aa.bb.cc.dd.ee.ff.gg"

# 최대 split 개수 구하기
max_len = df2['x'].apply(lambda x: len(x.split('.'))).max()

# 7번 반복하여 a를 컬럼 구분자로 받아주고, format 함수를 통해 a0, a1, a2,...로 표기
# lambda 함수를 통해 '.'으로 구분 -> 단, len(x.split('.'))보다 i가 작을 때 수행
for i in range(max_len):
	df2["a{}".format(i)] = df2['x'].apply(lambda x: x.split('.')[i] if len(x.split('.'))>i else None)
 
print(df2)

rrule

  • dateutil 라이브러리에 속한 함수

  • 날짜 데이터를 원하는 기준에 따라 output으로 가져올 수 있음

  • 주요 옵션

    • freq: 반복 주기를 나타내는 파라미터 (SECONDLY, MINUTELY, HOURLY, DAILY, WEEKLY, MONTHLY, YEARLY)
    • dtstart: 반복이 시작되는 날짜와 시간을 나타냄
    • interval: 주기적으로 반복되는 간격을 나타냄
    • count: 생성할 날짜의 최대 수를 나타냄
    • until: 반복이 끝나는 날짜와 시간을 나타냄
  • 문법 예시

# 라이브러리 
from datetime import datetime
from dateutil.rrule import rrule, DAILY, TU

# 시작 날짜, 종료 날짜
start_date = datetime(2024,2,1)
end_date = datetime(2024,3,1)

# 2024-02-01부터 2024-03-01까지 strf를 사용하여 원하는 데이터 형식으로 출력
weekly_rule = rrule(DAILY, dtstart=start_date, until=end_date)

for date in weekly_rule:
	print(date.strftime('%Y-%m-%d))
    
# 빈 리스트 생성 후 날짜 담기
a=[]
for date in weekly_rule:
	a.append(date.strftime('%Y-%m-%d))
    
# df3에 있는 날짜 데이터는 string이므로 string > datetime > string 형태로 변환
# 위에서 받은 리스트에 해당하는 데이터만 필터링하기 위함
df3['Time stamp2'] = pd.to_datetime(df3['Time stamp'].dt.strftime('%Y-%m-%d')

mask = df3['Time stamp2'].isin(a))
df3[mask]

일기

파이썬 라이브 세션 내용들을 복습하는데 아직 너무 어렵다,,
특히 lambda나 rrule 함수를 활용하는 부분은 많은 복습과 연습이 필요할 것 같다.

오늘은 하루종일 잠이 쏟아졌다. 아침부터 계속 졸았는데 점심 식사 이후에도 계속 졸려서 저녁 식사를 포기하고 잠을 자고 올 정도였다ㅜ.ㅜ 어쩔 수 없는 호르몬 이슈,, 그래도 내일은 괜찮을 것 같다. 내일은 꼭 판다스 공부 많이 해야지!!

0개의 댓글