본문 바로가기
빅데이터분석기사/작업형1

[작업형1] 섹션3 판다스 코드 정리

by nemonemonemo 2025. 6. 15.

Section1. 데이터 프레임과 시리즈

menu = pd.Series(['비빔밥','김치찌개','된장찌개'])

 

Section2. 데이터 저장 및 불러오기

# 저장 temp.csv
df.to_csv('temp.csv')

# 저장한 데이터 불러오기
temp_df = pd.read_csv('temp.csv')

 

Section3. 탐색적 데이터 분석 (EDA)

## 랜덤하게 샘플 확인
df.sample(3)


## 데이터 프레임 크기 (행, 컬럼)
df.shape 
#얘는 데이터 속성 보는 거라 소괄호 없음
#행-> 데이터 수
#열-> 컬럼 수

## 컬럼 형태(type)
df.info()
#각 컬럼의 데이터가 어떤 형태로 들어가있는지 확인

## 상관관계
df.corr(numeric_only=True) 
#numeric_only=True 이건 지금 데이터프레임에 objenct랑 int 섞여있어서 숫자형만 따지겠다는 말

## 항목 종류 수
df_car.nunique()

## 항목 종류
print(df_car['car'].nunique())
print(df_car['size'].nunique())
#출력 ['Sedan' 'SUV']
#출력 ['S' 'M' 'L']

# 항목별 개수
print(df_car['car'].value_counts())
print(df_car['size'].value_counts())
##value_counts에서 s 빼먹지마라

# 기초 통계 (숫자)
df.describe()

# 기초 통계 (문자)
df_car.describe(include='O')
##include='O'는 문자열(텍스트) 컬럼만 골라서 요약 통계(예: unique 값 개수, 최빈값 등)를 보여달라는 뜻
##문자열만 있는 데이터프레임이어도 describe()만 쓰면 아무것도 안 나오고,
##문자열 통계를 보고 싶으면 반드시 include='O'를 써야 합니다!

 

Section4. 자료형 변환

# 자료형 변환 float -> int
df['가격'] = df['가격'].astype('int')
##astype(int) -> 파이썬 내장 타입(클래스)으로 지정하는 방식
##보통 pandas 공식 문서나 예제에서는 문자열로 타입명을 지정하는 경우가 많습니다

 

Section5. 새로운 컬럼 추가 

# 새로운 컬럼 추가 (값은 0)
df['new'] = 0
##컬럼만 만들고 값을 안 넣으면 안 만들어짐

 

Section6. 데이터 삭제 (컬럼, 행)

# 행 삭제
df=df.drop(1, axis=0)
#axis=0 -> 행 선택
#axis=1 -> 열선택

 

Section7. 인덱싱/슬라이싱(loc)

# 인덱싱 (행 전체)
df.loc[0]
##얜 또 대괄호

# 카페라떼 가격
df.loc[1,'가격']

# 슬라이싱
# 카페모카 메뉴와 칼로리
df.loc[2, ['메뉴','칼로리']]
##[]리스트형태로 묶어야된다.

 

Section8. 인덱싱/슬라이싱(iloc)

# 슬라이싱 (카페모카와 카푸치노의 전체 데이터)
df.iloc[1:3]

# loc 슬라이싱 (카페모카와 카푸치노의 전체 데이터)
df.loc[2:3]
##얘는 2:3 이게 인덱스 이름을 가져오는 것이므로 마지막-1 로 생각하면 안 된다.

 

Section9. 데이터 추가/변경

# 딕셔너리 형태로 데이터(행) 추가
df.loc[7] =  {'메뉴':'딴짓커피','가격':'2000','칼로리':'20'}
##모든 컬럼 값을 채울 필요는 없음
##넣지 않은 컬럼 값은 결측치로 추가됨******

 

Section10. 정렬

# 인덱스 기준 정렬 (기본값 ascending=True)
df.sort_index(ascending=False)

# 값 기준 정렬 (기본값 ascending=True)
# 메뉴 기준 정렬
df.sort_values('메뉴', ascending=False)
##value 뒤에 s 까먹지마 

# 가격과 메뉴 기준 정렬
df = df.sort_values(['가격','메뉴'],ascending=[False,True])
##한 옵션이 아니라 여러개를 기준으로 정렬하고 싶을 때는
##여러개의 옵션을 리스트 형태로 만들어주면 된다. ##['가격','메뉴'] 이렇게!!
##그리고 메뉴 가격 똑같이 오름차순 or 내림차순으로 할 수도 있지만
##ascending=[False, True] 이렇게 가격은 내림차순으로, 메뉴는 오름차순으로 지정 가능

# 인덱스 새로 만들기 drop=True
df.reset_index(drop=True)
##정렬하면서 인덱스 명이 뒤죽박일 때 인덱스 새로 리셋
##drop=True 하는 이유는 이걸 하지 않으면 원래 인덱스가 새로운 컬럼으로 추가되니까

 

Section11. 필터링

# isin
df['메뉴'].isin(['녹차'])
##녹차가 있으면 T, 없으면 F 반환
##pandas의 isin() 메서드는 리스트 형태의 값을 요구하기 때문에,['녹차']처럼 꼭 대괄호를 써야 합니다. 
##위 코드처럼 ['녹차'] 하나만 넣어도!!!

 

Section12. 결측치 처리

# 컬럼별 결측치 확인
df.isnull().sum()
##이거로 컬럼별 결측치 개수 확인 가능

# 결측값 채우기
df['원산지'] = df['원산지'].fillna('코스타리카')
###'원산지'에서 결측치가 있던 모든 부분을 '코스타리카'로 채움

 

Section13. 값 변경

# 문자 변경 : 아메리카노 -> 룽고, 녹차 -> 그린티
# replace
df = df.replace('아메리카노','룽고')
df = df.replace('녹차','그린티')

# 딕셔너리 활용
change = {'아메리카노':'룽고','녹차':'그린티'}
df = df.replace(change)
##여러개 변경할 때 replace를 여러번 사용할 수도 있지만
##딕셔너리를 통해서 한 번에 변경할 수도 있음

# map() 함수
import pandas as pd
df = pd.DataFrame({'만족도': ['만족', '보통' ,'불만', '보통', '만족']}) #임의로 만든 데이터
#------------
mapping = {'만족':3, '보통':2, '불만':1}
df['만족도 숫자'] = df['만족도'].map(mapping)

 

Section14. 문자열

# 값 변경(str)
df['A'] = df['A'].str.replace('분석','시각화')
##문자의 일부를 변경하는 것은 replace만으로는 불가능*****************
##문자에서 일부만 변경할 때 str 접근자를 사용해서 변경할 수 있다
##숫자에서 쓰면 에러남

# 문자열 분리
df['A'].str.split()
##띄어쓰기를 기준으로 분리

# 각 행별 첫번째 요소 추출
df['D'] = df['A'].str.split().str[0]
##문자열 분리해서 그 중에 맨 앞 문자나 맨 뒤 문자만 뽑아서 새로운 컬럼으로 만들 수 있음
##df['A'].str.split() -> 'A' 컬럼의 각 값(문자열)을 공백 기준으로 분리
##.str[0] -> 위에서 분리된 리스트에서 첫 번째 요소를 선택
##df['D'] = -> 위 결과를 'D'라는 새로운 컬럼에 저장

# 문자 검색
df['A'].str.contains('기본')

#isin과 contains
menu = pd.Series(['맛난버거 세트', '매운 치킨버거', '더블 치즈버거'])
#---------------
menu.isin(['맛난버거 세트', '더블 치즈버거']) ##isin은 정확일치, 여러개 가능
menu.str.contains('세트') ##contains는 일부일치, 한개만

# 문자 길이
df['문자 길이'] = df['A'].str.len()
##공백도 하나의 문자로 인식******

#공백 제거
df['C'] = df['C'].str.replace(' ','')

# 문자열 슬라이싱
df['C'].str[1:3]
##C열의 각 행의 문자열의 두번째 글자부터 세번째 글자까지 슬라이싱함 -> abcd=> bc

# 행 선택
df['C'][1:3]
## 얜 그냥 C열의 두번째, 새번째 행을 보여줌

 

Section15. 내장함수

# 행의 수
print(len(df))
print(df.shape[0])
##shape에서 0 행, 1 열

# 조건
cond = df['가격'] > 5000
#-----------
#sum으로 조건에 맞는 개수 구하기
print(sum(cond))
#-----------
#len으로 조건에 맞는 개수 구하기
print(len(df[cond]))
##len으로 구하는게 더 복잡해
##len은 길이 구하는 거라 걍 다 세서 일단 먼저 df[cond]로 조건에 맞는 애들만 남기고
##그 다음에 len을 써서 개수를 세어야 조건에 맞는 개수를 셀 수 있음 

# 합계 (컬럼)
df.sum(numeric_only=True)
##drop이랑 sum은 반대!!!
##drop은 axis = 0 -> 행 삭제, axis = 1 -> 열 삭제
##sum은 그 반대라고 생각
##sum은 axis = 0 (기본) -> 열 별 합계, axis = 1 -> 행 별 합계

# 최대, 최소, 평균, 중앙, 합계, 표준편차, 분산
print("중앙값: ", df['가격'].median()) #중앙값

# 분위수
print('분위수 25% 값: ', df['가격'].quantile(.25))
print('분위수 75% 값: ', df['가격'].quantile(.75))

# 하위 25% 데이터
cond = df['가격'].quantile(.25) < df['가격']
df[cond]
##df['가격']는 DataFrame의 '가격' 컬럼(열) 전체를 의미
##df['가격'].quantile(.25)는 하나의 숫자 값

# 상위 25% 데이터
cond = df['가격'].quantile(.75) < df['가격']
df[cond]

# 최빈값 구하기
#mode
df['원산지'].mode()[0]
##최빈값이 여러개일 수 있음 그래서 시리즈 형태로 반환함***
##그래서 그 중에서 첫번째 값을 찾기 위해서 [0]라는 인덱스를 넣어줘야함***
## mode()[0] -> 이건 그냥 외워라~!! ***

# 최대값의 인덱스
df['가격'].idxmax()
##index of maximum이라고 생각해
###idmax로 오타내기 좋은 것 같음 정신차리자

# 가격 컬럼 중 가장 큰 값 3개
df.nlargest(3, '가격')

# 가격 컬럼 중 가장 작은 값 2개
df.nsmallest(2, '가격')

# apply 적용해서 새로운 컬럼 생성 (칼로리 컬럼 활용)
def cal(x):
  if x >= 100:
    return "No"
  else:
    return "Yes"
#-------------------
df['먹어도 될까요'] = df['칼로리'].apply(cal)
df

# melt
import pandas as pd
df = pd.DataFrame({'Name': {0: '쿼카', 1: '알파카', 2: '시바견'},
                   '수학': {0: 90, 1: 93, 2: 85},
                   '영어': {0: 92, 1: 84, 2: 86},
                   '국어': {0: 91, 1: 94, 2: 83},})
#-------------------------------------------------------------------
pd.melt(df, id_vars=['Name'])
##여러 개의 컬럼(수학, 영어, 국어)을 한 컬럼(variable)과 값(value)으로 녹여서(=melt) 긴 형태로 바꿉니다.
##id_vars=['Name']는 녹이지 않고 그대로 둘 컬럼을 지정
##여기서는 'Name'만 그대로 두고, 나머지 과목 점수 컬럼을 녹입니다.
##Name은 그대로 두고,
##'수학', '영어', '국어' 컬럼이 'variable' 컬럼에 들어가고,
##각 점수는 'value' 컬럼에 들어갑니다.
#-------------------------------------------------------------------
# melt - value 선택
pd.melt(df, id_vars=['Name'],value_vars=['수학','영어'])
#-------------------------------------------------------------------
# melt 컬럼명 설정
pd.melt(df, id_vars=['Name'], var_name='과목', value_name='점수')
##이런 형태로 바꾸면 조건문을 사용하기 쉽기 때문에
##실무에서는 melt로 재구조화해서 사용하는 경우가 많다

 

Section16. 그룹핑

# 원산지 기준, 평균
df.groupby('원산지').mean(numeric_only=True)
##df.groupby(['원산지']).mean(numeric_only=True)
##조건을 여러개 넣을 때 리스트 형태로 [] 대괄호 묶어서 사용하므로 대괄호 넣는 습관을 들이는 것도 좋다.

# 원산지와 메뉴 기준 (평균, 합계)
df.groupby(['원산지','메뉴']).agg(['mean','sum'])

# 1개 인덱스 형태로 리셋
df.groupby(['원산지','칼로리']).mean(numeric_only=True).reset_index()
##정렬하면서 인덱스 명이 뒤죽박일 때 인덱스 새로 리셋
##drop=True 하는 이유는 이걸 하지 않으면 원래 인덱스가 새로운 컬럼으로 추가되니까
##여기서는 원래의 숫자인덱스 없었으니까 drop=True할 필요없음****

# transform
#-----------------------------------------------------------------------------------------
import pandas as pd
# 데이터 생성 (일부 결측값 포함)
df = pd.DataFrame({
    '과일': ['딸기', '블루베리', '딸기', '블루베리', '딸기', '블루베리', '딸기', '블루베리'],
    '가격': [1000, None, 1500, None, 2000, 2500, None, 1800]  # 결측값 포함
})
df
#-----------------------------------------------------------------------------------------
df.groupby('과일').mean()
#--------------------------
#df.groupby('과일').mean() 여기서 가격만 선택하려면?
df.groupby('과일').mean()['가격']
##groupby('과일') -> 이건 함수에서 그룹바이 할 컬럼을 선택했으므로 소괄호()
##['가격'] -> 얘는 그 중에서 가격 컬럼을 선택했다는 것이므로 대괄호[]
###얘는 과일별로 가격 평균값을 반환하는 것
#--------------------------------------------------------------------------
# 과일별 평균 가격 구하기
price = df.groupby('과일')['가격'].transform('mean')
price
##얘는 원본 데이터프레임과 같은 길이의 시리즈로 각 행이 속한 과일의 평균 가격을 출력함
#---------------------------------------------------------------------------------
# 과일/등급별 평균 가격 구하기
price = df.groupby(['과일','등급'])['가격'].transform('mean')
price
##딸기 A등급의 평균과 딸기 B등급의 평균, 블루베리 A등급의 평균과 블루베리 B등급의 평균을 구하는 것
##과일과 등급 별로 평균 구할거니까 그룹바이에 넣고
##가격의 평균 구하니까 평균 구할 컬럼을 선택할 때 ['가격']으로 가격 컬럼 선택

# unstack
##unstack은 melt처럼 재구조화를 할 수 있는 함수
#-----------------------------------------------------------------------------
import pandas as pd
coffee_data = {
    '커피종류': ['아메리카노', '아메리카노', '아메리카노', '라떼', '라떼', '라떼'],
    '컵크기': ['Small', 'Medium', 'Large', 'Small', 'Medium', 'Large'],
    '판매량': [120, 150, 200, 100, 130, 180]
}
df = pd.DataFrame(coffee_data)
df
#-------------------------------------------------------------------------------
# groupby 적용
##커피종류와 컵 크기를 기준으로 판매량을 모두 더하는 그룹바이 적용
grouped = df.groupby(['커피종류','컵크기'])['판매량'].sum()
grouped
#---------------------------------------------------------------
# 컵크기를 컬럼으로 변환
grouped.unstack()
##unstack을 쓰면 가장 마지막의 인덱스를 컬럼으로 변경 가능
##여기서는 컵크기가 가장 마지막 인덱스이므로 그게 컬럼으로 변환됨
#----------------------------------------------------------------
# 커피종류를 컬럼으로 변환
grouped.unstack(level=0)
##unstack()는 기본적으로 level=-1이다
##level=-1은 가장 마지막 인덱스를 뜻함, 그걸 컬럼으로 변환하겠다는 뜻
##level=0으로 하면 가장 첫번째 인덱스를 컬럼으로 변환하겠다는 뜻
##여기서는 커피종류가 레벨0이 될 것
#----------------------------------------------------------------
# 두 번의 unstack 적용
grouped.unstack().unstack()
##다시 원상복구 되었지만 컵크기와 커피종류 위치가 바뀐 것을 볼 수 있음

 

Section19. 데이터 합치기

import pandas as pd

# 에피타이저 메뉴
appetizer = pd.DataFrame({
    'Menu': ['Salad', 'Soup', 'Bread'],
    'Price': [5000, 3000, 2000]
})

# 메인 메뉴
main = pd.DataFrame({
    'Menu': ['Steak', 'Pasta', 'Chicken'],
    'Price': [15000, 12000, 10000]
})
#----------------------------------------------------

# 두 메뉴를 수직으로 연결
full_menu = pd.concat([appetizer, main], ingnore_index=True)
##appetizer,main은 모두 변수 이름이므로 따옴표를 쓰지 않음
##만약 pd.concat(["appetizer", "main"])처럼 쓰면,
##이건 문자열 "appetizer"와 "main"을 리스트로 넣은 것이 되어버려요.
##결과적으로 pd.concat() 함수는 데이터프레임이 아니라 문자열을 받게 되어 에러가 납니다.
#----
##ignore_index=True 이걸 안 해주면 위에서 인덱스 그대로 가지고와서 012012 이렇게 됨
##ignore_index=True 이렇게 설정해줘야 순서대로 인덱스 잘 매겨짐

# 두 메뉴를 좌우로 연결
full_menu = pd.concat([appetizer, main], axis = 1)
##기본이 수직임
##axis=1 이게 좌우인지 잘 기억이 안 날 떄는 그냥 출력해보고 치는 것을 추천

#------------------------------------------------------
# 메뉴와 가격
price = pd.DataFrame({
    'Menu': ['Salad', 'Soup', 'Steak', 'Pasta'],
    'Price': [5000, 3000, 15000, 12000]
})

# 메뉴와 칼로리
cal = pd.DataFrame({
    'Menu': ['Soup', 'Steak', 'Pasta','Salad'],
    'Calories': [100, 500, 400, 150]
})
#------------------------------------------------------

# 두 데이터프레임을 'Menu'를 기준으로 병합
menu_info = pd.merge(price, cal, on='Menu')

 

Section20. 피벗테이블

=> 먼저 최종적으로 만들 데이터프레임을 생각하자.

import pandas as pd
# 직원별 부서 및 급여 정보
data = {
    '이름': ['서아', '다인', '채아', '예담', '종현', '태헌'],
    '부서': ['개발', '기획', '개발', '기획', '개발', '기획'],
    '급여': [3000, 3200, 3100, 3300, 2900, 3100]
}
df = pd.DataFrame(data)
print("[원본 데이터]")
print(df)
#-------------------------------------------------------------------
# 부서별 평균 급여 계산
pt = df.pivot_table(index = '부서', values='급여', aggfunc='mean')
print('\n[부서별 평균 급여]')
print(pt)

# 부서 및 직급별 급여 합계 계산
pt = df.pivot_table(index='부서', columns='직급', values='급여', aggfunc='sum')
print('\n[부서 및 직급 별 급여 합계]')
print(pt)
##columns='직급', values='급여' 이 부분 틀림
##직급을 index에 같이 리스트로 묶어서 넣어버렸고, vals라고만 했다가 틀림 정신차리자****
##index에 리스트로 묶어서 넣는 거 아님-> 경우에 따라 그런 경우도 있지만 지금은 아님


#-----------------------------------------------------------------------------------
# 다양한 집계를 위한 데이터셋
import pandas as pd
df = pd.DataFrame({
    "구분": ["전자", "전자", "전자", "전자", "전자", "가전", "가전", "가전", "가전"],
    "유형": ["일반", "일반", "일반", "특수", "특수", "일반", "일반", "특수", "특수"],
    "크기": ["소형", "대형", "대형", "소형", "소형", "대형", "소형", "소형", "대형"],
    "수량": [1, 2, 2, 3, 3, 4, 5, 6, 7],
    "금액": [2, 4, 5, 5, 6, 6, 8, 9, 9]
})
print(df)
#-------------------------------------------------------------------------------------
# 단일 값에 대해 집계
pt = df.pivot_table(
    index=['구분','유형'],
    columns='크기',
    values='수량',
    aggfunc='sum'
)
pt

# 단일 값에 대해 집계 (누락 값 0 처리)
pt = df.pivot_table(
    index=['구분','유형'],
    columns='크기',
    values='수량',
    aggfunc='sum',
    fill_value=0
)
pt
##fill_value=0 -> 결측값이 생기면 0으로 채운다는 뜻

# 여러 열에 대해 각기 다른 집계 함수 적용
pt = df.pivot_table(
	index=['구분','크기'],
    values=['수량','금액'],
    aggfunc={'수량':'mean','금액':'mean'}
)
##각기 다른 집계함수 쓰려면 aggfunc에 {} 중괄호 써서 딕셔너리 형태로 넣어야함!!!!!!!!!!!!