3주차

Suhyeon Lee·2024년 10월 21일
0

Pandas 알아보기

Pandas 불러오기

  • import 명령어를 통해서 pandas 라이브러리를 불러올 수 있음
import pandas as pd 
# pandas 라이브러리를 불러올 것이며 
# 이제부터 pandas를 pd라고 부를게!

# 에러날 경우 !pip install pandas  #실행

데이터 불러오기/저장하기

1) 데이터 불러오기

파일 경로 찾는 방법

  • Window

    1. 파일 탐색기(File Explorer)를 사용
      : 파일 탐색기를 열고 원하는 파일 또는 폴더를 찾은 후, 주소 표시줄(Address Bar)에 표시된 파일 경로를 복사하여 사용하거나, 마우스 오른쪽 버튼을 클릭하고 "속성(Properties)"을 선택하면 파일 또는 폴더의 속성 창에서 경로를 확인할 수 있음
    2. 명령 프롬프트(Command Prompt)를 사용
      : 명령 프롬프트(cmd)를 열고, cd 명령어를 사용하여 원하는 디렉토리로 이동한 후 pwd 명령어를 입력하면 현재 디렉토리의 경로를 확인할 수 있음
  • Mac

    1. Finder를 사용
      : Finder를 열고, 원하는 파일 또는 폴더를 찾은 후, 상단의 경로 표시줄(Address Bar)에 표시된 파일 경로를 복사하여 사용하거나, 파일 또는 폴더를 선택한 후 마우스 오른쪽 버튼을 클릭하여 "정보 보기(Get Info)"를 선택하면 파일 또는 폴더의 경로를 확인할 수 있음
    2. 터미널(Terminal)을 사용
      : 터미널을 열고, pwd 명령어를 입력하면 현재 작업 디렉토리의 경로를 확인할 수 있음

엑셀/CSV 데이터 불러오기

# pd.read_excel('파일경로/파일명.확장자')

# 엑셀 불러오기
pd.read_excel('./파일명.xlsx') 
# ./ → 현재 내가 있는 위치라는 의미

# csv 파일 불러오기
pd.read_csv('./파일명.xlsx')

인덱스(Index)

  • 데이터프레임(DataFrame) 또는 시리즈(Series)의 각 행 또는 각 요소에 대한 식별자
    • DataFrame 자료구조에도 인덱스를 설정할 수 있음
    • 0부터 시작하는 숫자 뿐아니라 임의로 문자로 적용할 수 있음
    • 아예 처음부터 파일 불러올 때, 인덱스를 지정하는 것도 가능

특징

  • 고유성(Uniqueness)
    • 각 행은 유일한 인덱스 값을 가져야 함
    • 중복된 인덱스 값을 가질 수 없음
  • 불변성(Immutability)
    • 한 번 생성된 인덱스는 변경(수정)할 수 없음
    • 단, 새로운 값을 할당하여 기존 인덱스를 대체하는 것은 가능
# Pandas에서 사용자가 직접 설정한 인덱스를 변경하는 예시

import pandas as pd

# 사용자가 직접 인덱스를 설정한 데이터프레임 생성
df = pd.DataFrame({'A': [1, 2, 3]\
, 'B': ['a', 'b', 'c']}\
, index=['idx1', 'idx2', 'idx3'])

# 인덱스 변경 (대체)
df.index = ['new_idx1', 'new_idx2', 'new_idx3']

print(df)

줄바꿈(indent) 기호: \

  • 코드가 너무 길어 나누고 싶을 때 사용
  • 조작 및 탐색(Manipulation and Retrieval)
    • 인덱스를 사용하여 데이터프레임 또는 시리즈의 특정 행을 선택하거나 탐색 가능
  • 정렬(Sorting)
    • 인덱스를 기준으로 데이터프레임 또는 시리즈의 행을 정렬할 수 있음

예시

  1. 기본 인덱스
    • Pandas는 기본적으로 0부터 시작하는 정수 인덱스를 제공
    • 데이터프레임을 생성할 때 자동으로 부여되는 인덱스
import pandas as pd

# 기본 정수 인덱스를 가진 데이터프레임 생성
df = pd.DataFrame({'A': [1, 2, 3], 'B': ['a', 'b', 'c']})
  1. 사용자 지정 인덱스
    • 사용자가 직접 인덱스를 설정할 수도 있음
# 사용자가 직접 인덱스를 설정한 데이터프레임 생성
df = pd.DataFrame({'A': [1, 2, 3], 'B': ['a', 'b', 'c']}, index=['idx1', 'idx2', 'idx3'])
  1. 인덱스 활용하기
    • 인덱스를 활용하여 데이터에 접근하거나 조작할 수 있음
    • set_index()
      • 특정 컬럼에 들어있는 값을 인덱스로 활용
    • (데이터프레임명).index를 통해 인덱스를 확인할 수 있음
    • reset_index()
      • reset_index() 를 활용해서 현재 인덱스를 0부터 시작하는 정수로 변경할 수 있음
# 특정 인덱스의 행에 접근
row = df.loc['idx2']

# 인덱스를 기준으로 데이터프레임 정렬
sorted_df = df.sort_index()

#인덱스 확인하기
data.index

#리스트 형태를 활용해서 인덱스를 새로 입력할 수 있습니다.
data.index = ['1번' , '2번' , '3번']
data

# reset_index() 의 기본 값은 drop = False 를 가지고 있습니다.
data.reset_index()

# 현재 인덱스를 컬럼으로 변경할 수 있습니다.

# reset_index(drop = True) 명령어를 활용하면,
# 현재 인덱스 값을 컬럼으로 변경하지 않고 인덱스를 초기화할 수 있습니다
data.reset_index(drop=True)

컬럼(Column)

  • 데이터프레임(DataFrame)의 열(또는 변수)
    • 데이터프레임은 행과 열로 구성되며, 각 열은 서로 다른 종류의 데이터를 담고 있음
    • 데이터프레임의 세로 방향에 있는 데이터들을 컬럼이라고 부름

특징

  • 고유한 이름(라벨)을 가지고 있으며, 해당 컬럼의 데이터를 식별하는 데 사용
  • 특정한 종류의 데이터를 담고 있고 숫자, 문자열, 날짜 등 다양한 유형의 데이터를 포함할 수 있음
  • 시리즈(Series) 객체로 구성
    • 시리즈: 동일한 데이터 유형을 가진 1차원 배열과 유사함
  • 데이터프레임의 일부로 간주되며, 해당 열의 데이터를 조작하고 접근할 수 있는 인터페이스를 제공함

예시

import pandas as pd

# 데이터프레임 생성
data = {
    '이름': ['Alice', 'Bob', 'Charlie'],
    '나이': [25, 30, 35],
    '성별': ['여', '남', '남']
}

df = pd.DataFrame(data)

# 각 컬럼 출력
print(df['이름'])  # '이름' 컬럼 출력
print(df['나이'])  # '나이' 컬럼 출력
print(df['성별'])  # '성별' 컬럼 출력
  • '이름', '나이', '성별'은 데이터프레임의 각 컬럼을 나타냄

컬럼명 변경하기

  • names = [’컬럼명1’ , ‘컬럼명2’ , … , ‘컬럼명 19’]
  • (데이터프레임명).column을 통해 컬럼을 확인할 수 있음
pd.read_csv('./data/file.csv' , names = [’컬럼명1, ‘컬럼명2,,‘컬럼명 19])

#컬럼 확인하기
data.column

#리스트 형태를 활용해서 컬럼명을 새롭게 입력할 수 있습니다.
data.column = ['축구', '농구', '배구', '야구']
data

⁉️ 파일이 깨져서 불러와져요!!

  • Pandas에서 파일을 불러올 때 파일의 텍스트 데이터를 읽어오는 과정에서 파일의 인코딩 방식을 정확히 지정해야 올바르게 데이터를 읽어올 수 있음
    • 인코딩: 한글과 같은 Ascii 범위를 벗어난 문자를 표현하기 위한 변형 작업
    • 모두가 하나의 인코딩을 사용하면 괜찮겠지만, 이러한 인코딩 방식은 여러 가지임
      • 한글만 하더라도 대표적으로 Microsoft사에서 만든 cp949/ms949 인코딩, euc-kr인코딩, utf-8 인코딩 등등 수많은 인코딩이 존재
      • 즉, 인코딩이 동일하지 않기 때문에 파일이 만약 cp949로 인코딩이 되어 있다고 가정했을 때 이 파일을 utf-8 인코딩 방식으로 읽어오려고 한다면, 잘못된 Byte 변환을 하기 때문에 깨짐 현상이 일어남
import pandas as pd
# UTF-8 인코딩으로 파일 불러오기
data = pd.read_csv('file.csv', encoding='utf-8')
# ASCII 인코딩으로 파일 불러오기
data = pd.read_csv('file.csv', encoding='ascii')

2) 데이터 저장하기

  • pd.to_csv(’파일경로/파일명.확장자’ , index = False)
  • pd.to_excel(’파일경로/파일명.확장자’ , index = False)
df = 데이터프레임 # 저장하고 싶은 데이터

df.to_csv('./newfile.csv', index = False)

데이터 확인

  • 데이터가 잘 들어왔는지, 이상은 없는지 확인

1) 데이터 확인

  • 데이터를 N개 행까지 보여줌
    • 기본은 5개 행
data.head() # head()은 기본 5개 행에 대한 데이터를 보여줌
data.head(3) # ()안에 숫자만큼 데이터를 보여줌

.info()

  • 데이터의 정보를 파악
    • 인덱스, 컬럼명, 컬럼의 데이터 개수, 데이터 타입
data.info() 
# null 값을 확인할때도 활용

.describe()

  • 데이터의 기초통계량을 확인
    • 개수, 평균, 표준편차, 사분위, 중앙값
  • 숫자값에 대해서만 → 데이터 타입이 int, float
data.describe()
# 숫자값에 대해서만 기초통계량 확인이 가능합니다.

데이터 불러온 후 꼭 확인해야 하는 것

데이터 결측치(null)가 있는가?

  • 결측치 제거하는 방법
    • 결측치 확인
      • isna, isnull: 결측값이면 True 반환
        ※ isnull: isna의 별칭(na보다는 null이라는 단어에 익숙한 경우 쓸 수 있게 지정)
      • notna, notnull: 결측값이면 False 반환
# 결측치 확인 : isnull(), isna()
df.isnull().sum() # 이렇게하면 결측치가 몇 개 있는지도 알 수 있어요 !

# 결측치 제거 : dropna()
df.dropna()

중복 데이터가 있는가?

  • 중복 데이터 제거하는 방법
# 중복 데이터 확인
df.duplicated(subset=['컬럼1', '컬럼2', '컬럼3'])

# 중복 데이터 제거
df.drop_duplicates(subset=['컬럼1', '컬럼2', '컬럼3'])

데이터 이상치가 있는가?

# IQR 계산
Q1 = df['컬럼1'].quantile(0.25)
Q3 = df['컬럼1'].quantile(0.75)
IQR = Q3 - Q1

# 이상치 기준 설정
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR

# 이상치 제거
df[(df['컬럼1'] >= lower_bound) & (df['컬럼1'] <= upper_bound)]

사분범위(InterQuartile Range, IQR)

  • 중앙값(Median)을 기준으로 데이터들이 흩어진 정도를 뜻함
  • 지속적으로 수신되거나 분포되는 데이터에서 이상치를 찾는 데 효과적
  • IQR = Q3 - Q1
    • 3사분위 수(Q3, 전체 데이터의 75% 값)와 1사분위 수(Q1, 전체 데이터의 25% 값)의 차
  • 위 식에서 계산된 IQR은 정상 데이터 범위의 최솟값과 최댓값이 계산됨
    • Minimum=Q1−(IQR∗1.5)
    • Maximum=Q3+(IQR∗1.5)
      → 새로 수신되거나 입력된 데이터가 Minimum보다 작거나 Maximum보다 크다면 그 데이터를 이상치로 판단할 수 있고, Minimum보다 크거나 Maximum보다 작으면 정상 데이터로 판단할 수 있음

타입이 알맞게 들어가 있는가?

  • e.g. 날짜, 숫자
# 데이터 타입 변경을 원한다면 ! 
df['column_name'].astype(int)
df['column_name'].astype(float)
df['column_name'].astype(str)
df['column_name'].astype(bool)
df['column_name'].astype('category')
df['column_name'].astype('datetime64[ns]')
df['column_name'].astype(complex)
df['column_name'].astype(object)

데이터 통계도 목적에 따라 확인해야 함

2) 데이터 타입 변경

astype을 사용한 데이터 타입 변경

  • 데이터 타입 확인
    • (데이터프레임명)['컬럼명'].dtype
      • 각 열의 데이터 타입을 한 번에 확인하려면 (데이터프레임명).dtypes 사용

💡 데이터 타입

데이터 타입(Data Type)설명(Description)예시(Example)
int64, int32정수형 데이터 (64비트 또는 32비트)1, 42, -10, 1000
float64, float32부동 소수점 수 (64비트 또는 32비트)3.14, -0.001, 2.718
object문자열 데이터 (일반적으로 문자열)'Hello', 'Data Science'
bool불리언(참/거짓) 데이터True, False
datetime64날짜와 시간 데이터'2023-12-31 08:00:00'
timedelta64시간 간격(두 날짜 또는 시간 사이의 차이) 데이터'3 days', '2 hours'
category카테고리형 데이터 (제한된 고유 값으로 구성)'Red', 'Blue', 'Green'
  • astype()는 Pandas 데이터프레임의 열의 데이터 타입을 변경하는 데 사용
    • 열의 데이터 타입을 원하는 형식으로 변환 가능
DataFrame['column_name'] = DataFrame['column_name'].astype(new_dtype)
  • DataFrame['column_name']
    • 열을 선택하는 방식
    • 열의 데이터 타입을 변경하고자 하는 열을 지정
  • new_dtype
    • 변경하고자 하는 새로운 데이터 타입을 명시
      • 'int', 'float', 'str' 등

예시: int → float

import pandas as pd

# 예시 데이터프레임 생성
data = {'integer_column': [1, 2, 3, 4, 5]}
df = pd.DataFrame(data)

# 정수형 열을 부동소수점으로 변환
df['integer_column'] = df['integer_column'].astype(float)
print(df.dtypes)  # 데이터프레임의 열 타입 확인

예시: int → str

import pandas as pd

# 예시 데이터프레임 생성
data = {'numeric_column': [1, 2, 3, 4, 5]}
df = pd.DataFrame(data)

# 숫자열을 문자열로 변환
df['numeric_column'] = df['numeric_column'].astype(str)
print(df.dtypes)  # 데이터프레임의 열 타입 확인

데이터 선택: slicing & selection

  • 원하는 형태로 데이터 선택 가능

1) lioc, loc

.iloc[row, column]

  • 정수 기반의 인덱스 사용: 인덱스 번호로 선택하기
data.iloc[0,2]
#행과 열 번호를 통해 특정 데이터를 선택할 수 있음
  • 행 번호(row)와 열 번호(column)를 통해 특정 행과 열 데이터를 선택할 수 있음
import pandas as pd

# 샘플 데이터프레임 생성
data = {
    'A': [1, 2, 3, 4, 5],
    'B': [10, 20, 30, 40, 50],
    'C': [100, 200, 300, 400, 500]
}
df = pd.DataFrame(data)

# iloc을 사용하여 특정 행과 열 선택
selected_data = df.iloc[1:4, 0:2]  # 인덱스 1부터 3까지의 행과 0부터 1까지의 열 선택
print(selected_data)

# 슬라이싱도 가능
df.iloc[0::2]

.loc[row, column]

data.loc['행이름' , '컬럼명']
# 행이름과 컬럼명을 통해서도 특정 데이터를 선택할 수 있음
  • 인덱스가 번호가 아니고 특정 문자일 경우: 이름으로 선택하기
import pandas as pd

# 샘플 데이터프레임 생성
data = {
    'A': [1, 2, 3, 4, 5],
    'B': [10, 20, 30, 40, 50],
    'C': [100, 200, 300, 400, 500]
}
df = pd.DataFrame(data, index=['a', 'b', 'c', 'd', 'e'])

# loc을 사용하여 특정 행과 열 선택
selected_data = df.loc['b':'d', 'A':'B']  # 레이블 'b'부터 'd'까지의 행과 'A'부터 'B'까지의 열 선택
print(selected_data)

※ .iloc에서 슬라이싱을 할 때는(Python 슬라이싱에서 "숫자값"인 경우) 마지막 인덱스를 포함하지 않고 그 전까지의 값을 가져옴
※ 반면 .loc에서 인덱스명을 입력해 슬라이싱을 할 때는 해당 값을 포함하여 데이터를 불러옴

1개의 컬럼 전체를 선택할 경우

  • 리스트 슬라이싱 활용
data.loc[: , '컬럼명']

#또는 데이터프레임['컬럼명'] 으로도 동일한 값을 선택할 수 있습니다.
data['컬럼명']
  • 여러 개의 컬럼을 선택할 경우에도 리스트를 활용해 선택 가능
data[   ['컬럼명1', '컬럼명2', '컬럼명3' ]   ] 
  • 여러 개의 컬럼을 선택할 때, 내가 원하는 순서대로 데이터 선택 가능
data[   ['컬럼명3', '컬럼명1', '컬럼명2' ]   ] 

2개 이상의 셀을 선택할 경우

  • 리스트 형태를 활용해 데이터 선택
# 2개 컬럼명을 선택할 경우
data.loc[  '행이름'  , ['컬럼명1' , '컬럼명2']   ]

# 2개 행이름을 선택할 경우
data.loc[  ['행이름1', '행이름2'] , '컬럼명1'    ]

# 리스트 슬라이싱 : 을 활용해서 특정 범위를 지정하여 선택할 수 있습니다.
data.loc[ '행이름' , '컬럼명1' : ] # '컬럼명1' : ==> 컬럼명1부터 끝까지라는 의미

2) 조건에 따라 데이터 선택하기(Boolean Indexing)

Boolean Indexing

  • 조건을 이용하여 데이터프레임에서 특정 조건을 만족하는 행을 선택하는 방법
  • 데이터를 필터링하거나 원하는 조건을 만족하는 행을 추출할 수 있음
  • 주로 불리언(Boolean) 값을 가지는 조건식을 사용하여 데이터프레임을 인덱싱하는 방법
    • 조건식에 따라 각 행이 True 또는 False로 평가되며 이를 바탕으로 데이터프레임을 필터링

사용 방법

단일 조건 필터링

  • 특정 열의 값을 기준으로 조건을 설정하여 해당 조건을 만족하는 행을 선택
# 'age' 열에서 30세 이상인 행 필터링
df[df['age'] >= 30]

여러 조건 필터링

  • 여러 개의 조건을 조합하여 복합적인 필터링을 수행
# 'age' 열에서 30세 이상이면서 'gender' 열이 'Male'인 행 필터링
df[(df['age'] >= 30) & (df['gender'] == 'Male')]

# 'age' 열에서 30세 이상이거나 'gender' 열이 'Male'인 행 필터링
df[(df['age'] >= 30) | (df['gender'] == 'Male')]

조건에 따른 특정 컬럼 필터링

  • 조건을 만족하는 특정 열만 선택
# 'age' 열에서 30세 이상인 경우의 'name' 열만 선택
df.loc[df['age'] >= 30, 'name']

isin() 활용 필터링

  • 리스트를 활용하여 여러 값들을 포함하는 행을 선택
# 'gender' 열에서 'Male' 또는 'Female'인 행 필터링
df[df['gender'].isin(['Male', 'Female'])]

isin() method

  • Series(시리즈)나 DataFrame(데이터프레임)의 값들 중에서 특정 값이나 리스트 안에 포함된 값들을 찾아내는 메서드
  • 원하는 조건에 해당하는 데이터를 빠르게 필터링하거나 선택할 수 있음
  1. 단일 값 포함 여부 확인
# Series나 DataFrame의 특정 열에서 단일 값이 포함되어 있는지 여부를 확인합니다.
import pandas as pd
data = {'A': [1, 2, 3, 4, 5],
        'B': ['apple', 'banana', 'orange', 'grape', 'melon']}
df = pd.DataFrame(data)
# 'B' 열에서 'banana' 값이 있는지 확인
result = df['B'].isin(['banana'])
print(result)
  1. 여러 값 포함 여부 확인
# 여러 값이 포함된 데이터를 찾기 위해 리스트에 여러 값을 넣어 사용합니다.
# 'A' 열에서 2 또는 4 값을 포함하는 행 찾기
result = df['A'].isin([2, 4])
print(result)
  1. 데이터프레임 전체에서의 사용
# 데이터프레임 전체에서 여러 열에 대해 isin()을 사용할 수 있습니다.
# 데이터프레임 전체에서 여러 조건을 확인하여 필터링
result = df.isin({'A': [1, 3], 'B': ['apple', 'orange']})
print(result)

실습: 특정 조건을 만족하는 데이터 선택

  • 비교 연산자 활용
# 예를들어, data['컬럼명1']이 숫자(int)값인 경우
data['컬럼명1'] < 80

# 80보다 작으면 True 
# 80보다 크면 False 을 반환합니다.
  • 조건을 통해 True/False로 반환된 값을 활용해서 True에 해당하는 값만 불러올 수 있음
    • 반환된 값을 변수에 할당한 다음 데이터프레임에 넣을 수 있음
condition = data['컬럼명1'] < 80
condition
data[condition]
  • 여러 개 조건을 활용해 값을 불러올 수 있음
    • 조건이 여러 개로 복잡할 때에는 변수에 할당해서 처리하는 게 코드적으로 깔끔함
      • 변수에 할당해서 정리하는 습관 들이기!
# 조건1 and 조건2 ==>> 조건1,2 둘 다 만족해야 한다 True
## and 를 &로 대체해서 사용할 수 있음

condition1 = data['컬럼명1'] < 80
condition2 = data['컬럼명2'] >= 50

condition = condition1 & condition2
data[conditon]


# 조건1 or 조건2 ==>> 조건1과 조건2 둘 중 하나만 만족하면 True
## or 를 |로 대체해서 사용 가능

condition1 = data['컬럼명1'] < 80
condition2 = data['컬럼명2'] >= 50

condition = condition1 | condition2
data[conditon]


# ()로 구분해서 조건을 한번에 입력해도 동일하게 활용할 수 있습니다.
condition = (data['컬럼명1'] < 80) & (data['컬럼명2'] >= 50)
data[conditon]

# 이렇게도 가능합니다.
data[(data['컬럼명1'] < 80) & (data['컬럼명2'] >= 50)]

# 조건이 많아서 행이 길어질 경우, 줄바꿈(indent)을 통해 구분해주시면 훨씬 가독성이 올라갑니다.
condition = (data['컬럼명1'] < 80) \
					& (data['컬럼명2'] >= 50)\
					& (data['컬럼명3'] >= 10)
data[conditon]

3) 데이터 추가하기

데이터 프레임에 컬럼 추가

df = pd.DataFrame()

df['컬럼명'] = data
# df라는 데이터프레임에 '컬럼명'이라는 이름의 컬럼이 추가되고,해당 컬럼에 data라는 값이 추가된다.
# 이때, data값이 1개의 단일 값인 경우에는 전체 df라는 데이터프레임 행에 data 값이 전체 적용됨
# 즉, 
# 하나의 값인 경우 => 전체 모두 동일한 값 적용
# (리스트,시리즈)의 형태인 경우 => 각 순서에 맞게 컬럼 값에 적용됨

신규 컬럼 추가

df = pd.DataFrame()

# 컬럼 추가하기
df['EPL'] = 100
df['MLS'] = 60
df['NBA'] = 70

df


# 리스트 형태로 컬럼값 추가하기
df['KFC'] = [50, 10, 30]
#Tip. 행 수를 맞춰서 입력해줘야함


# 컬럼을 여러 조건 및 계산식을 통해 산출값으로도 추가 가능
df['ABC'] = (df['EPL'] + df['NBA']) * df['MLS'] * 2

데이터 병합

1) concat()

※ CONCATENATE(병합하다)

  • concat() 함수는 데이터프레임을 위아래로 혹은 좌우로 연결할 수 있음
    • axis
      • 연결하고자 하는 축(방향)을 지정
      • 기본값은 0으로, 위아래로 연결하는 경우에 해당
      • 1로 설정하면 좌우로 연결
    • ignore_index
      • 기본값은 False
      • 연결된 결과 데이터프레임의 인덱스를 유지
      • True로 설정하면 새로운 인덱스를 생성(기존 인덱스를 무시하고 새롭게 인덱스를 설정)
  • 병합하는 데이터프레임의 행과 열의 개수가 다른 경우 빈 값(NaN)으로 채워짐
import pandas as pd

# 두 개의 데이터프레임 생성
df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2'], 'B': ['B0', 'B1', 'B2']})
df2 = pd.DataFrame({'A': ['A3', 'A4', 'A5'], 'B': ['B3', 'B4', 'B5']})

# 위아래로 데이터프레임 연결
result_vertical = pd.concat([df1, df2], axis=0)
# 인덱스를 확인해 보면 기존 인덱스가 유지된 체 구성된 것을 확인 가능(반복되는 값 존재)

# 인덱스 리셋
result_vertical = pd.concat([df1, df2], axis=0).reset_index(drop=True)
# drop: 제거된 인덱스를 열에 추가할지 여부
# reset_index에서 drop의 기본값은 False
# cf. inplace: 원본 객체 변경 여부(기본값 False)

# 좌우로 데이터프레임 연결
result_horizontal = pd.concat([df1, df2], axis=1)

print("위아래 연결 결과:\n", result_vertical)
print("\n좌우 연결 결과:\n", result_horizontal)


2) merge()

  • SQL의 JOIN 연산과 유사한 방식
  • 주로 두 개 이상의 데이터프레임에서 공통된 열이나 인덱스를 기준으로 데이터를 병합할 때 활용
  • concat은 데이터프레임을 단순하게 위아래/좌우로 병합하는 메서드이고 merge는 특정 컬럼을 고려해 데이터를 병합하는 메서드임

주요 매개변수

  • leftright
    • 병합할 데이터프레임 중 병합되는 기준이 되는 왼쪽(left)과 오른쪽(right) 데이터프레임
  • how
    • 병합 방법을 나타내는 매개변수
    • 'inner', 'outer', 'left', 'right' 등의 옵션
      - 'inner': 공통된 키(열)를 기준으로 교집합
      - 'outer': 공통된 키를 기준으로 합집합
      - 'left': 왼쪽 데이터프레임의 모든 행을 포함하고 오른쪽 데이터프레임은 공통된 키에 해당하는 행만 포함
      - 'right': 오른쪽 데이터프레임의 모든 행을 포함하고 왼쪽 데이터프레임은 공통된 키에 해당하는 행만 포함
  • on
    • 병합 기준이 되는 열 이름(혹은 열 이름의 리스트)을 지정
    • left_onright_on: 왼쪽 데이터프레임과 오른쪽 데이터프레임에서 병합할 열 이름이 다른 경우에 사용

예시

import pandas as pd

# 두 개의 데이터프레임 생성
left_df = pd.DataFrame({'key': ['A', 'B', 'C', 'D'], 'value': [1, 2, 3, 4]})
right_df = pd.DataFrame({'key': ['B', 'D', 'E', 'F'], 'value': [5, 6, 7, 8]})

# 'key' 열을 기준으로 두 데이터프레임 병합
merged_df = pd.merge(left_df, right_df, on='key', how='inner')

print(merged_df)

데이터 집계

  • Group By를 통한 데이터 집계

1) groupby()

  • 데이터프레임을 그룹화하고, 그룹 단위로 데이터를 분할(split), 적용(apply), 결합(combine)하는 기능을 제공
  • 데이터프레임을 특정 기준에 따라 그룹으로 나누어 집계, 변환, 필터링 등을 할 수 있음
    • 그룹 생성
      • 기준 열(혹은 열들)을 지정하여 데이터프레임을 그룹으로 나눌 수 있음
    • 그룹에 대한 연산 수행
      • 그룹 단위로 원하는 연산(평균, 합, 개수 등)을 수행
    • 결과 결합
      • 각 그룹의 연산 결과를 하나의 데이터프레임으로 결합하여 새로운 데이터프레임을 생성

Group by 함수 사용

import pandas as pd

# 샘플 데이터프레임 생성
data = {
    'Category': ['A', 'B', 'A', 'B', 'A', 'B'],
    'Value': [1, 2, 3, 4, 5, 6]
}
df = pd.DataFrame(data)

# 'Category' 열을 기준으로 그룹화하여 'Value'의 연산 수행
grouped = df.groupby('Category').mean()

grouped_sum = df.groupby('Category').sum()
grouped_count = df.groupby('Category').count()
grouped_max = df.groupby('Category').max()
grouped_min = df.groupby('Category').min()

# 수치형 데이터의 경우에 연산이 가능

복수의 열을 기준으로 사용

import pandas as pd

# 샘플 데이터프레임 생성
data = {
    'Category': ['A', 'A', 'B', 'B', 'A', 'B'],
    'SubCategory': ['X', 'Y', 'X', 'Y', 'X', 'Y'],
    'Value': [1, 2, 3, 4, 5, 6]
}
df = pd.DataFrame(data)

# 'Category'와 'SubCategory' 열을 기준으로 그룹화하여 'Value'의 합 계산
grouped_multiple = df.groupby(['Category', 'SubCategory']).sum()

print(grouped_multiple)

다양한 집계 함수 적용

import pandas as pd

# 샘플 데이터프레임 생성
data = {
    'Category': ['A', 'A', 'B', 'B', 'A', 'B'],
    'SubCategory': ['X', 'Y', 'X', 'Y', 'X', 'Y'],
    'Value1': [1, 2, 3, 4, 5, 6],
    'Value2': [10, 20, 30, 40, 50, 60]
}
df = pd.DataFrame(data)

# 'Category'와 'SubCategory' 열을 기준으로 그룹화하여 각 그룹별 'Value1'과 'Value2'의 평균, 합 계산
grouped_multiple = df.groupby(['Category', 'SubCategory']).agg({'Value1': ['mean', 'sum'], 'Value2': 'sum'})

print(grouped_multiple)
  • 복수의 열을 기준으로 그룹화하여 데이터프레임을 조작하는 경우 groupby() 함수에 복수의 열을 리스트로 전달하여 원하는 그룹화 기준을 지정하고, agg() 함수를 사용하여 여러 열에 대해 다양한 집계 함수를 적용할 수 있음

2) pivot_table()

  • 데이터프레임에서 피벗 테이블을 생성하는 데 사용
    • Pivot Table?
      • 데이터를 재구성하여 요약, 집계된 정보를 보여주는 테이블 형태
  • 주어진 데이터를 사용자가 원하는 형태로 재배치하여 요약된 정보를 보기 쉽게 제공

피벗 테이블 생성

import pandas as pd

# 샘플 데이터프레임 생성
data = {
    'Date': ['2023-01-01', '2023-01-01', '2023-01-02', '2023-01-02', '2023-01-01'],
    'Category': ['A', 'B', 'A', 'B', 'A'],
    'Value': [10, 20, 30, 40, 50]
}
df = pd.DataFrame(data)

# 피벗 테이블 생성: 날짜를 행 인덱스로, 카테고리를 열 인덱스로, 값은 'Value'의 합으로 집계
pivot = df.pivot_table(index='Date', columns='Category', values='Value', aggfunc='sum')

print(pivot)

여러 열을 기준으로 생성

import pandas as pd

# 샘플 데이터프레임 생성
data = {
    'Date': ['2023-01-01', '2023-01-01', '2023-01-02', '2023-01-02', '2023-01-01'],
    'Category': ['A', 'B', 'A', 'B', 'A'],
    'SubCategory': ['X', 'Y', 'X', 'Y', 'X'],
    'Value': [10, 20, 30, 40, 50]
}
df = pd.DataFrame(data)

# 피벗 테이블 생성: 'Date'를 행 인덱스로, 'Category'와 'SubCategory'를 열 인덱스로, 값은 'Value'의 합으로 집계
pivot = df.pivot_table(index='Date', columns=['Category', 'SubCategory'], values='Value', aggfunc='sum')

print(pivot)

집계 함수를 다르게 적용

import pandas as pd

# 샘플 데이터프레임 생성
data = {
    'Date': ['2023-01-01', '2023-01-01', '2023-01-02', '2023-01-02', '2023-01-01'],
    'Category': ['A', 'B', 'A', 'B', 'A'],
    'Value1': [10, 20, 30, 40, 50],
    'Value2': [100, 200, 300, 400, 500]
}
df = pd.DataFrame(data)

# 피벗 테이블 생성: 'Date'를 행 인덱스로, 'Category'를 열 인덱스로, 값은 'Value1'과 'Value2'의 평균과 합으로 집계
pivot = df.pivot_table(index='Date', columns='Category', values=['Value1', 'Value2'], aggfunc={'Value1': 'mean', 'Value2': 'sum'})

print(pivot)

시각화(맛보기)

  • Group by 나 Pivot Table 함수를 통해 원하는 형태로 데이터를 가공하고 시각화 할 수 있음
import matplotlib.pyplot as plt

import pandas as pd

# 샘플 데이터프레임 생성
data = {
    'Date': ['2023-01-01', '2023-01-01', '2023-01-02', '2023-01-02', '2023-01-01'],
    'Category': ['A', 'B', 'A', 'B', 'A'],
    'Value1': [10, 20, 30, 40, 50],
    'Value2': [100, 200, 300, 400, 500]
}
df = pd.DataFrame(data)

# 피벗 테이블 생성: 'Date'를 행 인덱스로, 'Category'를 열 인덱스로, 값은 'Value1'과 'Value2'의 평균으로 집계
pivot = df.pivot_table(index='Date', columns='Category', values=['Value1', 'Value2'], aggfunc='mean')


# 피벗 테이블의 선 그래프 시각화
pivot.plot(kind='line')
plt.xlabel('Date')
plt.ylabel('Values')
plt.title('Pivot Table Visualization')
plt.legend(title='Category')
plt.show()

3) 데이터 정렬하기

sort_values()

  • 컬럼 기준으로 정렬
import pandas as pd

# 샘플 데이터프레임 생성
data = {
    'Name': ['Alice', 'Bob', 'Charlie', 'David', 'Eva'],
    'Age': [25, 22, 30, 18, 27],
    'Score': [85, 90, 75, 80, 95]
}
df = pd.DataFrame(data)

# 정렬
sorted_by_score = df.sort_values('Score') # 'Score' 열을 기준으로 오름차순 정렬
sorted_by_score = df.sort_values('Score',ascending=False) # 'Score' 열을 기준으로 내림차순 정렬

print(sorted_by_score)

sort_index()

  • 인덱스를 기준으로 정렬
import pandas as pd

# 샘플 데이터프레임 생성
data = {
    'Name': ['Alice', 'Bob', 'Charlie', 'David', 'Eva'],
    'Age': [25, 22, 30, 18, 27],
    'Score': [85, 90, 75, 80, 95]
}
df = pd.DataFrame(data)

# 정렬
sorted_by_index = df.sort_index() # 인덱스를 기준으로 오름차순 정렬
sorted_by_index = df.sort_index(ascending=False) # 인덱스를 기준으로 내림차순 정렬
print(sorted_by_index)

기타: pickle

  • 데이터를 저장하고 불러오는 pickle에 대해 간단히 알아보기

pickle

  • python 의 변수, 함수, 객체를 파일로 저장하고 불러올 수 있는 라이브러리
  • list, dictionary 등을 파일 그대로 저장하면 용량이 매우 커지는데 pickle을 사용하면 binary 형태로 저장되기 때문에 용량이 매우 작아짐
  • 추가적으로 gzip을 이용하여 pickle로 저장된 데이터를 압축할 수 있음
    • pandas에서는 to_pickle()read_pickle() 메서드를 통해 pickle을 사용할 수 있음
  • 머신러닝 모델 등을 저장하고 불러올 때도 활용

저장하기

import pandas as pd

# 샘플 데이터프레임 생성
data = {
    'Column1': [1, 2, 3, 4, 5],
    'Column2': ['A', 'B', 'C', 'D', 'E']
}
df = pd.DataFrame(data)

# 데이터프레임을 pickle 파일로 저장
df.to_pickle('dataframe.pkl')  # 데이터프레임을 'dataframe.pkl' 파일로 저장

불러오기

import pandas as pd

# pickle 파일에서 데이터프레임 불러오기
loaded_df = pd.read_pickle('dataframe.pkl')  # 'dataframe.pkl' 파일에서 데이터프레임 불러오기
print(loaded_df)

숙제

Seaborn 내장데이터 셋을 활용해 데이터 전처리하기

iris 데이터셋을 활용해 전처리 해보기

import seaborn as sns
iris_data = sns.load_dataset('iris')

Q1. 'species' 열 값이 'setosa'인 데이터 선택하기

setosa_data = iris_data.loc[iris_data['species'] == 'setosa']

Q2. 10부터 20까지의 행과 1부터 3까지의 열 선택하기

subset = iris_data.iloc[10:21, 1:4]

tips 데이터셋을 활용해 전처리 해보기

import seaborn as sns
tips_data = sns.load_dataset('tips')

Q1. total_bill이 30 이상인 데이터만 선택하기

filtered_data = tips_data[tips_data['total_bill'] >= 30]

Q2. 성별('sex')을 기준으로 데이터 그룹화하여 팁(tip)의 평균 계산

grouped_by_sex = tips_data.groupby('sex')['tip'].mean()

Q3. 'day'와 'time'을 기준으로 데이터 그룹화하여 전체 지불 금액(total_bill)의 합 계산

grouped_by_day_time = tips_data.groupby(['day', 'time'])['total_bill'].sum()

Q4. 'day' 열을 기준으로 각 요일별로 팁(tip)의 평균을 새로운 데이터프레임으로 만든 후, 이를 기존의 tips 데이터셋에 합쳐보기

avg_tip_per_day = tips_data.groupby('day')['tip'].mean().reset_index()
avg_tip_per_day.columns = ['day', 'avg_tip']
merged_data = pd.merge(tips_data, avg_tip_per_day, on='day', how='left')

정답 코드

  • iris 데이터셋
import seaborn as sns
# 데이터셋 불러오기
iris_data = sns.load_dataset('iris')
# 데이터 확인
print(iris_data.head())
# loc 예시: 특정 조건의 데이터 선택
# 'species' 열 값이 'setosa'인 데이터 선택
setosa_data = iris_data.loc[iris_data['species'] == 'setosa']
# 선택된 데이터 확인
print("Setosa 데이터:")
print(setosa_data.head())
# iloc 예시: 특정 인덱스 범위의 데이터 선택
# 10부터 20까지의 행과 1부터 3까지의 열 선택
subset = iris_data.iloc[10:21, 1:4]
# 선택된 subset 데이터 확인
print("\nSubset 데이터:")
print(subset)
  • tips 데이터셋
import seaborn as sns
import pandas as pd
# 데이터셋 불러오기
tips_data = sns.load_dataset('tips')
# 데이터 확인
print("Tips 데이터셋:")
print(tips_data.head())
# total_bill이 30 이상인 데이터만 선택
filtered_data = tips_data[tips_data['total_bill'] >= 30]
print(filtered_data.head())
# 'sex'를 기준으로 데이터 그룹화하여 팁(tip)의 평균 계산
grouped_by_sex = tips_data.groupby('sex')['tip'].mean()
# 그룹화된 데이터의 통계적 요약 확인
print("\n성별에 따른 팁 평균:")
print(grouped_by_sex)
# 'day'와 'time'을 기준으로 데이터 그룹화하여 전체 지불 금액(total_bill)의 합 계산
grouped_by_day_time = tips_data.groupby(['day', 'time'])['total_bill'].sum()
# 그룹화된 데이터의 통계적 요약 확인
print("\n요일과 시간별 전체 지불 금액 합계:")
print(grouped_by_day_time)
# 'day'별 평균 팁 데이터 생성 및 확인
avg_tip_per_day = tips_data.groupby('day')['tip'].mean().reset_index()
avg_tip_per_day.columns = ['day', 'avg_tip']
print("\n요일별 평균 팁 데이터:")
print(avg_tip_per_day)
# 'day' 열을 기준으로 기존의 tips 데이터셋과 새로 생성한 데이터셋 merge
merged_data = pd.merge(tips_data, avg_tip_per_day, on='day', how='left')
# 병합된 데이터 확인
print("\n병합된 데이터:")
print(merged_data.head())
profile
2 B R 0 2 B

0개의 댓글