* 개인적인 스터디를 위한 블로그이기 때문에 생략된 부분이 많은 점 참고 부탁드립니다.
Series & DataFrame
1. Series
구분 | 내용 | 코드 예시 |
정의 | Pandas에서 사용하는 일종의 리스트 | |
생성 | Dictionary → Series | import pandas as pd dic = {'a':1, 'b':2, 'c':3} dic_series = pd.Series(dic) print(type(dic_series)) print(dic_series) |
List → Series - 인덱스 미설정시 자동으로 0부터 |
ls = [1, 2, 3] ls_series1 = pd.Series(ls) ls_series2 = pd.Series(ls, index=['a', 'b', 'c']} print(type(ls_series1)) print(ls_series1) print(type(ls_series2)) print(ls_series2) |
|
속성 확인 | - 시리즈의 값 : 시리즈명.values - 인덱스 : 시리즈명.index - 값의 타입 : 시리즈명.dtypes |
print(ls_series2.values) print(ls_series2.index) print(ls_series2.dtypes) |
2. DataFrame
구분 | 내용 | 코드 예시 |
정의 | 시리즈를 이어붙여 표 형태로 만든 것 | |
생성 | Dictionary → DataFrame - 열 단위로 값을 입력할 때 딕셔너리 사용 - 값의 길이가 모두 같아야 함. |
dic = {'Name':['John', 'Merry', 'Chris'] , 'Number':[1, 2, 3] , 'Month':['Feb', 'Oct', 'Nov']} df = pd.DataFrame(dic) df |
List → DataFrame - 행 단위로 값을 입력할 때 리스트 사용 - 각 리스트의 길이가 같아야 함. |
ls = [['John', 1, 'Feb'] , ['Merry', 2, 'Oct'] , ['Chris', 3, 'Nov']] df = pd.DataFrame(ls, columns=['Name', 'Number', 'Month']) df |
|
type(df) | ||
Series → DataFrame | name_series = pd.Series(['John', 'Merry', 'Chris']) number_series = pd.Series([1, 2, 3]) month_series = pd.Series(['Feb', 'Oct', 'Nov']) df = pd.DataFrame({'Name':name_series, 'Number':number_series, 'Month':month_series}) df |
|
속성 확인 | - 데이터프레임의 값 : 데이터프레임명.values - 인덱스 : 데이터프레임명.index - 값의 타입 : 데이터프레임명.dtypes - 컬럼 : 데이터프레임명.columns |
print(df.values, end='\n\n') print(df.index, end='\n\n') print(df.dtypes, end='\n\n') print(df.columns) |
데이터 불러오기, 저장하기
1. csv 파일
구분 | 내용 | 코드 예시 |
불러오기 | 데이터변수 = pd.read_csv(파일경로) - index_col : 인덱스로 사용할 컬럼 - usecols : 사용할 컬럼 * 내용에 한글 포함되어 있다면, encoding='utf-8' 혹은 'cp949' |
csv_file_path = './data/titanic_train.csv' # 파일 경로 csv_data1 = pd.read_csv(csv_file_path, index_col='PassengerId', usecols=['PassengerId', 'Survived', 'Pclass', 'Age']) # index_col = 0 가능 csv_data1.head() |
저장 | 데이터변수 = pd.to_csv(파일경로) | csv_file_path1 = './data/csv_test.csv' csv_data1.to_csv(csv_file_path1) pd.read_csv(csv_file_path1).head() |
2. 엑셀 파일
구분 | 내용 | 코드 예시 |
불러오기 | 데이터변수 = pd.read_excel(파일경로, sheet_name=시트이름) - header : 컬럼 이름으로 사용할 행 - index_col : 인덱스로 사용할 컬럼 - usecols : 사용할 컬럼 |
!pip install openpyxl excel_file_path = './data/titanic_train.xlsx' excel_data = pd.read_excel(excel_file_path, sheet_name='시트1') excel_data.head() |
excel_data1 = pd.read_excel(excel_file_path, sheet_name='시트1', header=1, index_col='PassengerId', usecols=['PassengerId', 'Survived', 'Pclass', 'Age']) excel_data1.head() |
||
저장하기 | 데이터변수.to_csv(파일경로, sheet_name=시트이름) |
excel_file_path1 = './data/excel_test.xlsx' excel_data1.to_excel(excel_file_path1, sheet_name='sheet1') pd.read_excel(excel_file_path1, sheet_name='sheet1').head() |
데이터 가공
1. 조회
구분 | 내용 | 코드 예시 |
행 조회 | 한 개 - 데이터프레임명[인덱스:인덱스+1] 여러 개 - 데이터프레임명[시작인덱스:끝인덱스+1] |
df[3:4] df[3:6] df[:10] |
열 조회 | 한 개 - 데이터프레임명[컬럼명] - 데이터프레임명.컬럼명 여러 개 - 데이터프레임명[[컬럼명1, 컬럼명2, …]] |
df['Survived'] # Series 형태로 출력 df.Survived # Series df['Survived'].to_frame() # 데이터프레임 형태로 출력 df[['Survived']] # 데이터프레임 df[['Survived', 'Pclass', 'Name']] # 데이터프레임 |
loc | 레이블 값을 사용하여 조회 - 데이터프레임명.loc[행조건, 열조건] - 열만 조회할 때는 행조건에 : 를 입력 |
df.loc[3, ] # 3 행 df.loc[:, 'Name'] # 'Name' 열 df.loc[3, 'Name'] df.loc[3:5, ['Age', 'Pclass']] # 3~5행 df.loc[[1, 3, 5], ['Age', 'Pclass']] |
특정 열을 인덱스로 설정했다면 | df1 = df.set_index('Name') # Name 열을 인덱스로 설정 df1.loc[['Heikkinen, Miss. Laina', 'Allen, Mr. William Henry', ]] |
|
iloc | 위치 인덱스를 사용하여 조회 - 데이터프레임명.iloc[행인덱스조건, 열인덱스조건] |
df.iloc[3, ] df.iloc[3:7, ] df.iloc[[1, 3, 5], ] df.iloc[3:7, 2:4] |
2. 조건
구분 | 내용 | 코드 예시 |
정렬 | 데이터프레임명.sort_values(정렬기준컬럼) - 내림차순 : ascending=False |
df.sort_values('Age', ascending=False) df.sort_values(['Age', 'Fare'], ascending=[False, True]) |
조건 | 데이터프레임명[조건식] 데이터프레임명.query('조건식') |
df[(df['Pclass'] == 1) & (df['Age'] >= 30)] df[(df['Pclass'] == 1) | (df['Age'] >= 30)] df.query('Pclass == 1 and Age >= 30') df.query('Pclass == 1 or Age >= 30') |
.isin(리스트) - 리스트 안의 값을 가지는 행 추출 |
df[df['PassengerId'].isin([3, 100, 500])] df.query('PassengerId in [3, 100, 500]') df.query('PassengerId in @passengerid_sample') # 변수명 앞에 @ 붙임. df.query('PassengerId.isin([3, 100, 500])') |
3. 인덱스. 행, 열
구분 | 내용 | 코드 예시 |
인덱스 | 확인 | df.index print(list(df.index)) |
변경 인덱스 몇 개를 바꿀 때 - 데이터명.rename({인덱스1:바꿀인덱스1, 인덱스2:바꿀인덱스2, …}) 인덱스 전체를 바꿀 때 - 데이터명.index = 바꿀인덱스리스트 |
df1.rename({0:'row1', 1:'row2'}) # 변경하려면 변수에 저장해야 함. df1 = df1.rename({0:'row1', 1:'row2'}) df1.index = [i+1 for i in range(len(df1))] |
|
열 → 인덱스 - 데이터명.set_index(컬럼명) |
df1 = df1.set_index(['PassengerId']) | |
인덱스 → 열 변환 후 열 남기고 싶으면, - 데이터명.reset_index() 변환 후 열 삭제하고 싶으면, - 데이터명.reset_index(drop=True) |
df1 = df1.reset_index() df1 = df1.reset_index(drop=True) |
|
행 | 행 추가 - pd.concat([기존테이블명, 붙일테이블명]) 행 제거 - 데이터명.drop(인덱스명, axis=0) 행 중복 제거 - 데이터명.drop_duplicates() |
df3 = pd.concat([df1, df2]) # 인덱스 891 부터 끝까지 drop df3 = df3.drop([i for i in range(891, len(df3))], axis=0) # axis=0은 행 df3 = df3.drop_duplicates() |
행 이동 | 데이터명[컬럼명].shift(이동할 행의 수) | df2['Temp shift1'] = df2['Temp'].shift(1) # 전일 대비 증감률 df2['pct change'] = (df2['Temp shift1'] - df2['Temp'])/df['Temp'] |
열 | 열 추가 - 데이터명[추가할 컬럼명] = 추가할 값 열 제거 - 데이터명.drop(제거할 컬럼명, axis=1) 열 이름 변경 열 이름 하나를 바꿀 때 - 데이터명.rename({열이름1:바꿀이름1, 열이름2:바꿀이름2, ...}, axis=1) 열 이름 전체를 바꿀 때 - 데이터명.columns = 열이름리스트 |
df1['age_simplified'] = df1['Age']//10 * 10 # 10대, 20대 단위 df1['given_name'] = [i[0] for i in df1['Name'].str.split(',')] # 이름이 첫번째 부분만 df1['string_add'] = df1['Sex'] + df1['given_name'] df1 = df1.drop('given_name', axis=1) df1 = df1.rename({'PassengerId':'Id'}, axis=1) # axis=1은 열 df1.columns = [i for i in range(12)] |
4. 결측값
구분 | 내용 | 코드 예시 |
확인 | isna() : 결측값을 True로 반환 notna() : 결측값을 False로 반환 |
# 컬럼별로 결측값이 몇 개인지 df.isna().sum() # 결측값 있는 행만 확인 df[df['Age'].isna()] # 컬럼별로 결측값 아닌 데이터가 몇 개인지 df.notna().sum() |
제거 | 데이터명.dropna(axis=0, how='any', subset=None) - axis: {0: index / 1: columns} - how: {'any': 존재하면 제거 / 'all': 모두 결측치면 제거} - subset: 행/열의 이름을 지정 |
df.dropna(axis=1) df.dropna(how='all') df.dropna(subset=['Cabin', 'Age']) |
대치 | 데이터 전체의 결측값을 특정 값으로 변경 - 데이터명.fillna(대치할값) 특정 컬럼의 결측값을 특정 값으로 변경 - 데이터명[컬럼명].fillna(대치할값) 결측값을 바로 위의 값과 동일하게 변경 - 데이터명.fillna(method='ffill') 결측값을 바로 아래의 값과 동일하게 변경 - 데이터명.fillna(method='bfill') |
df.fillna(-1) df['Age'] = df['Age'].fillna(-1) df['Age'] = df['Age'].fillna(round(df['Age'].mean())) # 특정 컬럼의 평균값으로 대치 df.fillna(method='ffill') df.fillna(method='bfill') |
5. 타입
구분 | 내용 | 코드 예시 |
확인 | .dtypes : 컬럼의 타입을 시리즈로 반환 특정 타입을 가진 컬람만 추출 - 데이터명.select_dtypes(타입) |
df.dtypes df.select_types(int) df.select_types('object') |
변환 | 데이터명[컬럼명].astype(타입) - 결측치가 있으면 정수로 반환할 수 없음. (fillna() → 변환 → replace()) |
df['PassengerId'].astype(str) df1['Age'].fillna(-1).astype(int).replace(-1, np.nan) |
6. 날짜
구분 | 내용 | 코드 예시 |
문자형 변경 | 날짜 계산을 위해 문자형 → 날짜형 pd.to_datetime(컬럼, format='날짜형식') - %Y : 0을 채운 4자리 연도 - %y : 0을 채운 2자리 연도 - %m : 0을 채운 월 - %d : 0을 채운 일 - %H : 0을 채운 시간 - %M : 0을 채운 분 - %S : 0을 채운 초 |
pd.to_datetime(df['Date'], format='%Y-%m-%d') |
날짜형 형식 변경 | 데이터명[컬럼명].dt.strftime(날짜형식) | df['Date1'].dt.strftime('%Y-%m') df['Date1'].dt.strftime('%m-%d %H:%M') |
dt 연산자 | dt.날짜형식 - year, month, day : 연도, 월, 일 - dayofweek : 요일 (0-월요일, 6-일요일) - day_name() : 요일을 문자열로 |
df['year'] = df['Date1'].dt.year df['month'] = df['Date1'].dt.month df['day'] = df['Date1'].dt.day df['dayofweek'] = df['Date1'].dt.dayofweek df['dayname'] = df['Date1'].dt.day_name() |
계산 | - day 연산 : pd.Timedelta(day=숫자) - month 연산 : DateOffset(months=숫자) - year 연산 : DateOffset(years=숫자) |
df['plus day1'] = df['Date1'] + pd.Timedelta(days=1) df['plus day7'] = df['Date1'] + pd.Timedelta(days=7) df['minus day7'] = df['Date1'] - pd.Timedelta(days=7) from pandas.tseries.offsets import DateOffset df['plus month1'] = df['Date1'] + DateOffset(months=1) df['minus month3'] = df['Date1'] - DateOffset(months=3) df['plus year1'] = df['Date1'] + DateOffset(years=1) df['minus year3'] = df['Date1'] - DateOffset(years=3) |
날짜 구간 데이터 | pd.date_range(start=시작일자, end=종료일자, periods=기간수, freq=주기) - freq='D' : 일별 - W : 주별 - M : 월별 말일 - MS : 월별 시작일 - A : 연도별 말일 - AS : 연도별 시작일 |
pd.date_range(start='2020-01-01', periods=30, freq='D') pd.date_range(start='2020-01-01', end='2023-06-30', freq='M') |
기간 이동 계산 | 데이터명[컬럼명].rolling().집계함수 - mean, sum, min, max 가능 |
# 7일 이동평균 df1['ma7'] = df['Temp'].rolling(7).mean() # 30일 이동평균 df1['ma30'] = df['Temp'].rolling(30).mean() # 7일 합계 df['Temp'].rolling(7).sum() |
7. 고급 기능
구분 | 내용 | 코드 예시 |
apply 함수 | 사용자 정의 함수를 데이터에 적용하고 싶을 때 사용 - .apply(함수, axis=0/1) |
# 사용자 정의 함수 def pclass_sibsp(x): if x['Pclass'] == 1 and x['SibSp'] == 1: return 1 else: return 0 df1['pclass_sibsp_filter'] = df1.apply(pclass_sibsp, axis=1) # 함수에 열 이름을 참조 했기 때문에 axis=1 |
간단한 함수는 lambda로 구현 가능 | df1['pclass_sibsp_lambda'] = df1.apply(lambda x: 1 if x['Pclass'] == 1 and x['SibSp'] == 1 else 0, axis=1) |
|
import numpy as np def adult(x): if x >= 19: return 1 elif x < 19: return 0 else: return np.nan df1['adult_yn'] = df1['Age'].apply(adult) |
||
map 함수 | - 값을 특정 값으로 치환하고 싶을 때 사용 - 데이터명[컬럼명].map(매핑 딕셔너리) |
gender_map = {'male':'남자', 'female':'여자'} df1['Sex_kr'] = df1['Sex'].map(gender_map) |
문자열 함수 | - .str.contains(문자열) : 문자열을 포함하고 있는지 유무 - .str.replace(기존문자열, 대체문자열) : 문자열 대치 - .str.split(문자열, expand=True/False, n=개수) : 특정 문자열을 기준으로 쪼개기 - .str.lower() : 소문자로 바꾸기 - .str.upper() : 대문자로 바꾸기 |
df2['Name'].str.contains('Mrs') # True/False로 반환 df2[df2['Name'].str.contains('Mrs')] # 데이터 추출: 대괄호에 넣으면 조건식이 됨. df2['Name'].str.replace(',', '') df2['Name'].str.split(' ') df2['Name'].str.split(' ', expand=True, n=1) # n은 ' '를 기준으로 몇개로 쪼갤 것인지 결정 df2['Name'].str.lower() df2['Name'].str.upper() |
8. 데이터 결합
구분 | 내용 | 코드 예시 |
join | 두 개의 데이터를 특정 컬럼 기준으로 합침. - pd.merge(데이터1, 데이터2, on=기준컬럼, how=결합방법) 두 데이터의 기준 컬럼명이 다른 경우 - pd.merge(데이터1, 데이터2, left_on=데이터1 기준컬럼, right_on=데이터2 기준컬럼, how=결합방법) |
pd.merge(customer, orders, on='id', how='inner') pd.merge(customer, orders, left_on='id', right_on='customer_id', how='inner') # 기준 컬럼 두 개가 모두 출력됨. |
'Python > 데이터 분석' 카테고리의 다른 글
[Python] 데이터 집계 (0) | 2024.09.02 |
---|