[LG헬로비전 DX DATA SCHOOL 4기] Python(7) (250114)

mini_bang·2025년 1월 13일

Pandas

Series 생성 및 기본 조작

  • Series 생성
// 실습 코드
import numpy as np
import pandas as pd

# Series는 첫 글자가 대문자
obj = pd.Series([0, 1, 2, 3, 4, 5, 6, 7], index = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])
obj
  • Integer location 접근
// 실습 코드
# integer location
print(obj[3])
print(obj[-1])
print(obj[[1, 3, 5]])
print(obj[1:3])
print(obj[obj < 3])
  • Label location 접근
// 실습 코드
# label location
print(obj['c'])
print(obj.c)
print(obj[['e', 'c']])
obj['d':'e'] = 100
print(obj)

iloc와 loc 사용

  • Integer location(iloc)
// 실습 코드
# integer location
print(obj.iloc[2])
print(obj.iloc[[2]]) # multi index (라벨이 나오냐 안나오냐의 차이)
print(obj.iloc[1:4])
  • Label location(loc)
// 실습 코드
obj.loc['a':'c']
print(obj)

DataFrame 생성 및 기본 조작

  • DataFrame 생성
// 실습 코드
frame = pd.DataFrame(np.arange(24).reshape(4, -1),
                     columns = ['c1', 'c2', 'c3', 'c4', 'c5', 'c6'],
                     index = ['r1', 'r2', 'r3', 'r4'])
print(frame)
  • 열 및 행 선택
// 실습 코드
print(frame['c3'])
print(frame.c3)
print(frame[['c1', 'c2']])
print(frame['r1':'r2'])
print(frame['c1':'c2'])   # 열만 출력됨!
print(frame[['c1', 'c2']])  # 멀티 인덱스로 접근해야하고 각각 콤마로 구분해줘야함

특정 위치 값 선택 (iloc와 loc)

// 실습 코드
print(frame.iloc[[0], [3]])
print(frame.loc[['r1'], ['c4']])
print(frame.iloc[[0, 1], 1:4])
print(frame.loc['r1':'r2', ['c2', 'c3', 'c4']])

Series 연산

  • Series 덧셈 및 NaN 처리
// 실습 코드
s1 = pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])
s2 = pd.Series([10, 20, 30, 40], index=['b', 'c', 'd', 'e'])
print(s1 + s2) # NaN : Not-a-Number  /  SQL : Outer Join

print(s1.add(s2, fill_value=0))   # 둘다 없는 경우에는 NaN으로 채워짐

데이터 필터링

  • 조건에 맞는 데이터 선택
// 실습 코드
# 데이터 필터링(조건에 맞는 데이터를 선택)
import numpy as np
import pandas as pd

df = pd.DataFrame({'A': ['foo', 'bar', 'foo', 'bar', 'foo', 'bar', 'foo', 'foo'],
                   'B': ['one', 'one', 'two', 'three', 'two', 'two', 'one', 'three'],
                   'C': np.random.randn(8),
                   'D': np.random.randn(8)})
print(df)

# A열의 foo만 나오는 dataframe을 출력해 보세요.
print(df[df['A'] == 'foo'])
  • 학생 DataFrame 생성 및 필터링
// 실습 코드
students = pd.DataFrame([
    [3, '김영광', 'M'],
    [13, '이은지', 'F'],
    [23, '조유경', 'F'],
    [4, '구재성', 'M'],
    [14, '주재경', 'M'],
    [24, '최지원', 'F']], columns = ['no', 'name', 'gender'])

print(students)
  • 조건 기반 필터링(비트 연산자)
// 실습 코드
# 비트연산자 '&' 사용
cond1 = students['no'] % 2 == 1  # no 컬럼의 값이 홀수이면
cond2 = students['gender'] == 'F'  # gender 컬럼의 값이 'F'이면
subset = students[cond1 & cond2]

print(subset)

CSV 데이터 읽기

  • CSV 파일 읽기 및 출력
// 실습 코드
df = pd.read_csv('/content/drive/MyDrive/LG헬로비전 DX School/250114/stock_2020_01.csv', encoding='cp949')
# /content/drive/MyDrive/LG헬로비전 DX School/250114/stock_2020_01.csv  => 절대경로
# ./(250114)stock_2020_01.csv : 상대경로  ./  -> 현재 경로로 들어가주세요.
# ../ -> 위 폴더로 옮겨주세요.    Ex) .././Downloads/stock_2020_01.csv  -> 위 폴더로 옮겨주시고 현재 경로로 접근해주세요.
# encodig
# CP949 : Windows
# UTF-8 -> MAX, Linux
print(df)
// 실습 코드
print(df.head()) # default : 5 (위에서 5개)
print(df.tail())  # 밑에서부터 5개
print(df['kospi'])

기술 통계량

  • 기술 통계 출력
// 실습 코드
# 기술 통계량
print(df.describe())    # 사분위수
print(df.info())
  • 평균 계산 및 조건 필터링
// 실습 코드
print(df['kospi'].mean())

# 평균보다 큰것만 출력해보세요.
print(df[df['kospi'] > df['kospi'].mean()])
  • 결측치 확인
// 실습 코드
# 결측치 확인하는 방법
print(df.isnull().sum())
print(df.isna().sum())

일별 변화율 계산 및 최대/최소 변화율 날짜 찾기

  • 변화율 계산 및 날짜 확인
// 실습 코드
# 일별 변화율 계산(변화율 = (오늘값 - 어제값) / 어제값 * 100)
df['kospi_change'] = df['kospi'].pct_change() * 100
df['kosdaq_change'] = df['kosdaq'].pct_change() * 100

# 변화율이 가장 큰 날 찾기
kospi_max_change_date = df.loc[df['kospi_change'].idxmax(), 'Date']
kospi_min_change_date = df.loc[df['kospi_change'].idxmin(), 'Date']

print(f'코스피 변화율 최대날 : {kospi_max_change_date}')
print(f'코스피 변화율 최소날 : {kospi_min_change_date}')
print(df.max())

DataFrame 기본 통계 및 축별 연산

  • 축별 최대값 계산
// 실습 코드
frame = pd.DataFrame([[10, 4, 3], [10, 2.5, 5], [np.NaN, 10, 6]],
                     index = ['i1', 'i2', 'i3'],
                     columns = ['c1', 'c2', 'c3'])
print(frame)
print(frame.max())
print(frame.max(axis=1))    # 0 : 행, 1 : 열

Series의 중복 제거 및 값 개수 계산

  • 유일값과 개수 계산
// 실습 코드
obj = pd.Series([2, 1, 3, 3, 1, 5, np.nan, 1, 2])
print(obj.unique())  # 중복되는 값을 제거하고 유일값만 담고 있는 Series 반환(순서를 정렬해서 반환하지는 않음)
# Series에서만 됨. dataframe에서는 되지 않음.

print(obj.value_counts())  # 값을 인덱스로 설정하고 그 값의 개수를 담고 있는 Series를 반환
print(obj.value_counts(normalize=True)) # 비율로 나타내줌

Series 정렬

  • 인덱스 정렬
// 실습 코드
obj = pd.Series([1, 2, 3, -1, -2], index=list('abebc'))
print(obj.sort_index())
obj = pd.Series([1, 2, 3, -1, -2], index=list('나마라다바'))  # 한글도 정렬 가능
print(obj.sort_index())
print(obj.sort_index(ascending=False))

Series 값 변환 (map)

  • Series 값 매핑
// 실습 코드
# map : series의 각각의 element들을 다른 어떤 값으로 대체하는 역할
series = pd.Series([100, 200, 300])
print(series.map({100 : "C", 200 : "B", 300 : "A"}))
print(series.map('${}'.format))
print(series.map('{}달러'.format))
f = lambda x : np.add(x, 3)
print(series.map(f))

Series 값 변환 (apply)

  • Series에 함수 적용
// 실습 코드
s = pd.Series([20, 21, 12], index=['London', 'New York', 'Helsinki'])
print(s)

def sub_custom_value(x, val):
  return x-val
print(s.apply(sub_custom_value, args=(10,)))    # args=(10)  =>  X    가변공간을 주어야함.
  • 키워드 인자 활용
// 실습 코드
def add_custom_values(x, **kwargs):
  for month in kwargs:
    x += kwargs[month]
  return x
print(s.apply(add_custom_values, june=30, july=20, august=25))

# kwargs에 들어 있는 키(june, july, august)를 반복문으로 순회하며, 각 값( 30, 20, 25)을 x에 더합니다.

DataFrame에 함수 적용 (apply & applymap)

  • 축별 연산 (apply)
// 실습 코드
frame = pd.DataFrame(np.arange(12).reshape(4, 3), index=['a', 'b', 'c', 'd'])
print(frame)

print(frame.apply(lambda x : x.max() - x.min()))
print(frame.apply(lambda x : x.max() - x.min(), axis=1))
  • 전체 값 연산 (applymap)
// 실습 코드
print(frame.applymap(lambda x : x**2))

행 및 열 삭제 (drop)

  • 행/열 삭제
  • 원본에 반영 (inplace)
// 실습 코드
# drop : row나 column에서 특정한 label을 삭제하는 함수
print(frame.drop('a'))
print(frame)  # 원본에 영향 주지 않음

print(frame.drop('0', axis=1))   # 열 인덱스를 설정하지 않아서 적용불가

# KeyError                                  Traceback (most recent call last)
# <ipython-input-83-d3bae25a84fd> in <cell line: 1>()
# ----> 1 print(frame.drop('0', axis=1))   # 열 인덱스를 설정하지 않아서 적용불가

# 3 frames
# /usr/local/lib/python3.10/dist-packages/pandas/core/indexes/base.py in drop(self, labels, errors)
#    7068         if mask.any():
#    7069             if errors != "ignore":
# -> 7070                 raise KeyError(f"{labels[mask].tolist()} not found in axis")
#    7071             indexer = indexer[~mask]
#    7072         return self.delete(indexer)

# KeyError: "['0'] not found in axis"
// 실습 코드
frame = pd.DataFrame(np.arange(16).reshape(4, 4),
                     columns = ['c1', 'c2', 'c3', 'c4'],
                     index = ['r1', 'r2', 'r3', 'r4'])
print(frame)
print(frame.drop('r1'))
print(frame.drop('c1', axis=1))    # 이러면 적용 가능, numpy와 pandas의 axis 0,1이 서로 반대임
print(frame.drop(columns = ['c3', 'c4']))

print(frame.drop(['r2'], inplace=True))  # inplace하면 원본에 영향줌, 가급적이면 새로운 변수에 할당하는 것을 권장
print(frame)

frame = frame.drop(['r3'])
print(frame)

Series 병합 및 DataFrame 병합

  • Series 병합 (concat)
// 실습 코드
s1 = pd.Series([100, 200], index = ['c', 'b'])
s2 = pd.Series([300, 300, 300], index = ['c', 'd', 'e'])
s3 = pd.Series([500, 600], index = ['f', 'g'])

print(s1, s2, s3, sep = '\n\n')
print(pd.concat([s1, s2, s3]))
print(pd.concat([s1, s2], axis=1))
  • DataFrame 병합 (merge)
// 실습 코드
data1 = pd.DataFrame({'id':['01', '02', '03', '04', '05', '06'],
                      'col1':np.random.randint(0, 50, 6),
                      'col2':np.random.randint(1000, 2000, 6)})
data2 = pd.DataFrame({'id':['04', '05', '06', '07'],
                      'col1':np.random.randint(1000, 5000, 4)})

# merge default -> inner join
print(pd.merge(data1, data2, on='id'))

결측치 처리

  • Series에서 결측치 제거
// 실습 코드
obj = pd.Series(['apple', 'mango', np.nan, None, 'peach', 1])
print(obj)
print(obj.dropna())
  • DataFrame에서 결측치 처리
// 실습 코드
frame = pd.DataFrame([[np.nan, np.nan, np.nan],
                     [10, 5, 40, 6], [5, 2, 30, 8],
                     [20, np.nan, 20, 6], [15, 3, 10, np.nan]],
                     columns = ['x1', 'x2', 'x3', 'x4'])
print(frame)

print(frame.dropna())
print(frame.dropna(how='all'))
print(frame.fillna(0))

중복 처리

  • 중복 확인 및 제거
// 실습 코드
# 중복 제거
# duplicated : 각 row가 중복인지(true) 아닌지(false) 알려주는 불리언 Series 반환
# drop_duplicates : duplicated를 적용한 결과가 Fasle인 것들만 모아서 dataframe 반환
data = pd.DataFrame({'id':['0001', '0002', '0003', '0001'],
                     'name':['a', 'b', 'c', 'a']})
print(data.duplicated())
print(data.drop_duplicates())

데이터 변형 (Binning)

  • 구간 나누기 (cut)
// 실습 코드
# 데이터 변형 - binning
# 변수에서 수치형 변수(연속형 변수)이면 회귀, 명목형 변수(categorial 변수)이면 분류 문제로 본다.
# cut : 메소드 결과는 categorial 객체
ages = [20, 35, 67, 39, 59, 44, 56, 77, 28, 20, 80, 32, 46, 52, 19, 33, 5, 15, 50, 29, 21, 33, 48, 85, 80, 31, 10]
bins = [0, 20, 40, 60, 80, 100]

cuts = pd.cut(ages, bins)
print(cuts)
print(cuts.value_counts())
  • 구간 레이블 지정 및 균등 분할
// 실습 코드
group_names = ['10대 이하', '20-30대', '40-50대', '60-70대', '70대 이상']
print(pd.cut(ages, bins, labels = group_names))

# 구간을 균등한 길이로 나눔
print(pd.cut(ages, 4, precision = 1).value_counts())
print(pd.qcut(ages, 4).value_counts())    # qcut : 개수들이 균등한 비율로 되도록 나누어줌

범주형 변수 변환 (One-Hot Encoding)

  • pd.get_dummies를 사용한 One-Hot Encoding
// 실습 코드
df = pd.DataFrame({'col1':[10, 20, 30],
                   'col2':['a', 'b', 'a']})
print(df)
df_dummies = pd.get_dummies(df, dtype=int)
print(df_dummies)       # sparse(0이 많은 상태) <-> dense(0이 없는 상태)

KBO 데이터프레임 기본 분석 예제

  • KBO 데이터 읽기 및 구조 분석
// 실습 코드
import numpy as np
import pandas as pd

kbo = pd.read_csv('/content/drive/MyDrive/LG헬로비전 DX School/250114/kbo.csv')
kbo

print(kbo.shape)
print(kbo.columns)
print(kbo['팀'].unique())
print(kbo.describe())
  • 그룹화 및 통계 분석
// 실습 코드
print(kbo.groupby('팀').count())    # 넥센에서 키움으로 이름이 바뀌어서 데이터가 이상함

print(kbo.groupby(['연도', '팀']).sum())

print(kbo.groupby('팀')['승률'].max())

print(kbo.groupby(['연도', '팀'])[['승률', '순위']].max())
  • 그룹별 데이터 확인
// 실습 코드
grouped = kbo.groupby('팀')
for name, group in grouped:
  print(name)
  print(group)
  print('-' * 50)
  • 특정 그룹 선택
// 실습 코드
print(grouped.get_group('한화'))
  • 그룹화 후 데이터 변형 및 필터링
    그룹별 변형 (agg)
// 실습 코드
print(grouped['순위'].agg([('함수', lambda val : val.max() - val.min())]))

print(grouped.agg({'순위':np.mean, '승률':[np.mean, np.std]}))

그룹 필터링 (filter)

// 실습 코드
print(kbo.groupby('팀').filter(lambda x : len(x) == 2))
print(kbo.groupby('팀').filter(lambda x : x['순위'].min() == 1))

데이터 분석 자동화 패키지 (ydata-profiling)

  • ydata-profiling을 이용한 자동 분석
// 실습 코드
!pip install ydata-profiling

from ydata_profiling import ProfileReport     # 자동으로 분석해서 시각화해주는 패키지
profile = ProfileReport(kbo, title = "Profiling Report")
profile

0개의 댓글