[데이터분석] Pandas - DataFrame
2024. 8. 13. 16:22ㆍAI & DS/머신러닝
DataFrame 생성
- pd.DataFrame(data)
- List 사용
date = [['초코파이', '몽쉘', '오예스'], ['오리온', '롯데', '해태'], [171, 170, 150], 5830, 5290, 4790]] df = pd.DataFrame(data)
- +) index명, column명 설정
date = [['초코파이', '몽쉘', '오예스'], ['오리온', '롯데', '해태'], [171, 170, 150], 5830, 5290, 4790]] df = pd.DataFrame(data, index='상품명', '제조사', '열량', '가격'], columns=['상품1', '상품2', '상품3'])
- +) index명, column명 설정
- Dictionary사용
data = {'상품1' : ['초코파이', '오리온', 171, 5830], '상품2' : ['몽쉘', '롯데', 170, 5290], '상품3' : ['오예스', '해태', 150, 4790]} df = pd.DataFrame(data, index = ['상품명', '제조사', '열량', '가격'])
- +) series 사용
product_1 = pd.Series({'상품명' : '초코파이', '제조사':'오리온', '열량':171, '가격':5830}) product_2 = pd.Series({'상품명' : '몽쉘', '제조사':'롯데', '열량':170, '가격':5290}) product_3 = pd.Series({'상품명' : '오예스', '제조사':'해태', '열량':150, '가격':4790}) df = pd.DataFrame({'상품1':product_1,'상품2':product_2,'상품3':product_3})
- +) series 사용
DataFrame 속성 확인
df.index # index명 확인
df.columns # column명 확인
df.shape # (행, 열) 크기 확인
df.head(n) # 데이터 상단 n개 행 출력
df.tail(n) # 데이터 하단 n개 행 출력
df.describe() # 칼럼(열)별 기술 통계량 출력
df.info # 칼럼(열)별 결측치, 데이터타입 등 출력
- 결측치 확인 및 처리
# 결측치 확인
df.isnull()
df.isnull().sum() #column별 결측치 수 확인
df.isna()
df.notnull()
df.notna()
# 결측치 처리
df.fillna('Normal') # 결측치 'Normal'로 채우기
df.dropna() # 결측치 포함하고 있는 행 삭제
DataFrame 데이터 선택
# index로 지정
df.set_index('Name', inplace = True) # 'Name'열을 index로 지정
# Row 선택
df.loc['부산']
df.iloc[1]
df.loc[['부산', '울산']] # 2개 이상 행 선택 시, 대괄호 2개 필요
# column 선택
df['최고기온'] # 칼럼명 사용
df[df.columns[1]] # index 번호 사용
# 특정 데이터 선택(열과 행 선택)
df.loc['행 이름', '열 이름'] # loc 사용 (행 먼저)
df.iloc[행 번호, 열 번호] # iloc 사용 (행 먼저)
df['열 이름'][행 번호] # column명 사용 (열 먼저)
- index로 지정
- 이제 df.set_index('Name', inplace=True)를 실행하면, 'Name' 열이 인덱스로 설정되어 데이터프레임이 다음과 같이 변경
- 'Name' 열이 인덱스가 되어 행을 식별하는 데 사용됨
- inplace=True로 설정했기 때문에 df는 원본 데이터프레임을 직접 수정함
import pandas as pd
data = {
'Name': ['Alice', 'Bob', 'Charlie'],
'Age': [25, 30, 35],
'City': ['New York', 'Los Angeles', 'Chicago']
}
df = pd.DataFrame(data)
df.set_index('Name', inplace=True)
- Column 선택
df['Speed']) # Speed열 선택
df['Speed'].mean() #포켓몬들의 Speed 평균값
df['Speed'].median() # 포켓몬들의 Speed 중앙값
# 데이터 필터링
df[df['Type 1'] == 'Water'] # 'Type 1'이 'Water'인 데이터 선택
df[df['HP'] >= 50] # 'HP'가 50 이상인 데이터 선택
df[(df['Type 1'] == 'Water') & (df['HP'] >= 50)] # 'Type 1'이 'Water'이고 'HP'가 50 이상인 데이터 선택
- 행과 열 선택
df.loc[:, ['Type 1', 'Type 2']] # 모든 포켓몬들의 Type 1, Type 2만 선택
df.iloc[2:11, 4] # index번호가 2부터 10까지인 포켓몬들의 HP(4) 선택
df.iloc[:10, 4:10] # 처음 10개 포켓몬들의 HP(4)부터 speed(9) 데이터 선택
DataFrame 데이터 수정
- 추가/삭제
# 행 & 열 추가
df.loc['새로운 행 이름'] = 데이터 값
df.['새로운 열 이름'] = 데이터 값
# 행 & 열 삭제
df.drop('행 이름', axis = 0)
df.drop('열 이름', axis =1;
df.drop('Unnamed: 0', axis = 1, inplace = True) # 'Unnamed: 0'column 삭제
# inplace 옵션을 사용하여 수정사항 저장
# HP, Attack, Defense, Sp. Atk, Sp. Def, Speed 모두 더하여
# 'Total' 이름의 column 추가
df['Total'] = df['HP'] +df['Attack']+df['Defense']+df['Sp. Atk']+df['Sp. Def']+df['Speed']
# 위의 과정을 .sum() 함수 이용하여 시행 -> 데이터 선택 방법: iloc을 사용한 슬라이싱
df['Total2'] = df.iloc[:, 4:10].sum(axis=1)
- 특정 데이터값을 다른 값으로 대체(replace 함수)
# 목표: Legendary 포켓몬 개수 세기
# 1단계) Legendary column에서 True는 1로, False는 0으로 바꾸기
# 원본 df에 수정사항 저장
df['Legendary'] = df['Legendary'].replace({True: 1, False: 0})
# 2단계) Legendary column 세로로 더하기
df['Legendary'].sum(axis=0)
- 정렬
# index 기준
df.sort_index(ascending=True) # 오름차순
df.sort_index(ascending=False) # 내림차순
# 데이터 값 기준
df.sort_values('최고기온', ascending=False)
df.sort_values('Type 1') # 동일한 Type 1끼리 정렬
df.sort_values(['Type 1', 'HP']) # 동일한 Type 1끼리 정렬, 동일한 Type 1내에서는 HP 오름차순으로 정렬
DataFrame 데이터 연산
.sum() # 데이터의 합
.mean() # 데이터의 평균
.std(), var() # 데이터의 표준편차, 분산
.min(), max() # 데이터의 최솟값, 최댓값 반환
.idxmin(), idxmax() # 데이터의 최솟값, 최댓값이 위치한 인덱스 반환
.median() # 데이터의 중앙값 반환
.quantile(n) # n분위 수 반환
.apply() # 괄호 안 함수를 모든 데이터에 적용
- 데이터 기술 통계량 확인
df.describe()
- 수치 데이터에 함수 적용(apply 함수)
# 목표: HP가 50미만인 포켓몬들에게 HP+20, Attack+20, Defense+20 하기
# HP가 50 미만인 포켓몬들의 HP, Attack, Defense를 각각 20씩 증가시키는 함수
def increase_stats(row):
if row['HP'] < 50:
row['HP'] += 20
row['Attack'] += 20
row['Defense'] += 20
return row
# apply를 사용하여 함수 적용
df.apply(increase_stats, axis=1)
- axis 가 1이어야하는 이유?
- df.apply(increase_stats, axis=1)에서 axis=1을 사용하는 이유는 각 행(row)에 대해 함수를 적용하기 위해서 이다.
- ↔ 반면에 axis=0은 각 열(column)에 대해 함수를 적용할 때 사용된다.
- axis=0 (Default): 각 열(column)에 대해 함수를 적용
- axis=1: 각 행(row)에 대해 함수를 적용
- 여기서 목표는 각 포켓몬의 HP, Attack, Defense 값을 수정하는 것이므로 각 행(row)을 기준으로 함수를 적용해야 하고 → 따라서 axis=1을 사용해야 한다.
import pandas as pd
data = {
'Name': ['Pikachu', 'Bulbasaur', 'Charmander'],
'HP': [35, 45, 39],
'Attack': [55, 49, 52],
'Defense': [40, 49, 43]
}
df = pd.DataFrame(data)
# increase_stats 함수는 각 포켓몬(row)의 HP가 50 미만인 경우,
# HP, Attack, Defense 값을 각각 20씩 증가시킴
def increase_stats(row):
if row['HP'] < 50:
row['HP'] += 20
row['Attack'] += 20
row['Defense'] += 20
return row
# 각 행(row)에 대해 함수 적용
df = df.apply(increase_stats, axis=1)
print(df)
- 만약 axis=0을 사용하면, 각 열(column)에 대해 함수를 적용하게 되므로 의도한 대로 작동하지 않는다.
df = df.apply(increase_stats, axis=0)
- 이 경우, 함수가 열 단위로 작동하므로 각 열의 값들을 순회하게 됨 → 따라서 각 행에 대해 함수를 적용하기 위해서는 axis=1을 사용해야 함
- 데이터 그룹화(groupby 함수)
# Type 1을 기준으로 데이터 그룹화, 그룹별 데이터 개수 확인
df.groupby('Type 1').count()
# Type 1을 기준으로 데이터 그룹화, 그룹별 데이터 값의 합 확인
df.groupby('Type 1').sum()
'AI & DS > 머신러닝' 카테고리의 다른 글
[데이터분석] 타이타닉 데이터셋 전처리 실습 (1) | 2024.08.13 |
---|---|
[데이터분석] 데이터 전처리 - Kaggle API 인증하기 (0) | 2024.08.13 |
[데이터분석] Pandas - Series (0) | 2024.08.13 |
[데이터분석] Pandas (0) | 2024.08.13 |
[데이터분석] Numpy배열 - indexing, slicing (0) | 2024.08.13 |