Python 프로그래밍 및 Pandas 활용 실습(2)
2024. 1. 3. 18:49ㆍTIL
Series 생성(Create)
# 참조 - import pandas
import pandas as pd
#Series 생성
numbers = list(range(3, 14))
pd.Series(numbers)
#Series 문자열 생성 및 인덱스 변환
letters = list('programmers')
pd.Series(letters, index=numbers)
# len(index) == len(values)
letters_index = [f'문자{i}' for i in range(1,12)]
# Dict -> Series
user = {
"name": "Spencer",
"age": 20,
"job": None
}
# key->index, value->value
pd.Series(user)
# Dict->Series 할 때 index를 지정하면
pd.Series(user, index=['name','age','address']) #address는 딕셔너리에 없으므로 value가 NaN
Series 속성(Attribute)
import pandas as pd
numbers = list(range(1, 7))
letters = list("spencer")
number_series = pd.Series(numbers)
letters_series = pd.Series(letters)
# dtype : 시리즈가 반환하는(담고있는) 데이터 타입
number_series.dtype #dtype('int64')
letters_series.dtype #dtype('O')
'''
- 기본적으로 object에 표현할 수 있는 데이터는 int64, float64 등으로 표현된다.
- '0'으로 dtype이 나온다면 object를 의미한다.
**주로 보이는 dtype들**
| dtype | 설명 |
|------------|--------------------------|
| int64 | 정수형 데이터 |
| float64 | 실수형 데이터 |
| object | 문자열 데이터 |
| bool | 불리언(참/거짓) 데이터 |
| datetime64 | 날짜 및 시간 데이터 |
| timedelta | 두 날짜 또는 시간 간격 데이터 |
| category | 카테고리 형식의 데이터 |
| int8 | 8비트 정수형 데이터 |
| int16 | 16비트 정수형 데이터 |
| int32 | 32비트 정수형 데이터 |
| float16 | 16비트 실수형 데이터 |
| float32 | 32비트 실수형 데이터 |
| complex64 | 64비트 복소수형 데이터 |
| complex128 | 128비트 복소수형 데이터 |
'''
#.index는 인덱스에 대한 정보를 준다.
number_series.index #RangeIndex(start=0, stop=6, step=1)
letters_series.index #RangeIndex(start=0, stop=7, step=1)
#.values는 데이터를 배열(Array)로 반환한다.
number_series.values #array([1, 2, 3, 4, 5, 6], dtype=int64)
letters_series.values #array(['s', 'p', 'e', 'n', 'c', 'e', 'r'], dtype=object)
.shape는 데이터의 구조를 알 수 있으며, Series는 1차원 구조다.
number_series.shape #(6,)
letters_series.shape #(7,)
.size는 데이터의 크기를 알 수 있다.
number_series.size #6
letters_series.size #7
hasnan은 None이나 NaN같은 결측치(Missing Data)가 있는지 확인한다.
number_series.hasnans #False
letters_series.hasnans #False
user = {
'name': 'Spencer',
'job': None
}
user_series = pd.Series(user)
user_series.hasnans #True
Series 메소드(Method)
메소드 = 객체 안에 있는 함수
import pandas as pd
scores = [90.5, 55.5, 81.4, None, 75.6]
score_series = pd.Series(scores)
#.max() - 최대값(Maximum value)
score_series.max()
#.idxmax() - 최대값의 인덱스
score_series.idxmax()
#.min() - 최소값(Minimum Value)
score_series.min()
#.idxmin() - 최소값의 인덱스
score_series.idxmin()
#.sum() - 합계
score_series.sum()
.mean() - 평균
score_series.mean()
#.isnull(), isna() - 결측치 체크 - 값(value)중 null 또는 not 유형의 데이터가 없는가?
score_series.isnull()
score_series.isna()
#.round() - 각 수치 반올림
score_series.round()
반올림 사사오입과 오사오입
- 학교에서 배운 반올림 - 사사오입 - Round off
- 반올림은 올림과 내림이 합쳐진 형태이나 정확히 반절 지점인 .5는 무조건 올림
- 이때 통계적으로 중립성이 깨짐(0.5 + 1.5 + 2.5 + 3.5 = 8.5에서 각 항목 값을 반올림하면 1 + 2 + 3 + 4= 10이 되어 전체 값이 1.5 증가)
- 즉, 통계학이나 빅데이터와 같은 많은 값을 다루는 분야에서라면 오차가 크게 발생
- Python의 반올림 원리 - 오사오십 - Round half to even
- 반올림할 숫자가 정확히 반절 위치일 경우, 가까운 짝수 쪽으로 반올림하는 규칙
- 반올림할 숫자가 절반일 경우에 그 결과는 무조건 짝수(0, 2, 4, 6, 8)
- 0.5 + 1.5 + 2.5 + 3.5 = 8.5에서 오사오입 방식으로 이용하여 가까운 짝수 쪽으로 반올림을 하면 0 + 2 + 2 + 4 = 8로, 오차는 0.5가 됨
- 이러한 이유로 파이썬에서 round(4.5)는 4, round(5.5)는 6
- 반올림을 하는 이유
- 소수점 이하 자릿수 조절
- 데이터의 정확도 제한
- 통계 분석
- 시각화
csv <> DataFrame 데이터 로드와 세이브
import pandas as pd
# csv 전체 가져오기 -> DataFrame
richest_dataset = pd.read_csv('TopRichestInWorld.csv')
# csv에서 특정 열만 가져오기 -> DataFrame
richest_dataframe = pd.read_csv('TopRichestInWorld.csv', usecols=['Name'])
# csv에서 특정 열만 Series로 가져오기 -> .squeeze() -> Series
richest_series = pd.read_csv('TopRichestInWorld.csv', usecols=['Name']).squeeze()
#새로운 csv파일 저장
richest_series.to_csv('TopRichestInWorld_New.csv')
# index는 제외하고 저장
richest_series.to_csv('TopRichestInWorld_New.csv',index=False)
#앞서 Series를 csv로 저장했으나 다시 csv로 데이터를 읽으면 무조건 DataFrame
richest_data = pd.read_csv('TopRichestInWorld_New.csv')
Series-조회(head, tail)
import pandas as pd
rich_df = pd.read_csv('TopRichestInWorld.csv')
#.head()는 앞측 데이터를 원하는 만큼 볼 수 있다.
rich_df.head() # =rich_df.head(5)
rich_df.head(10)
#.tail()은 뒷측 데이터를 원하는 만큼 볼 수 있다.
rich_df.tail() # =rich_df.tail(5)
rich_df.tail(10)
Series-값 정렬(sort_values, axis=, ascending=, kind=, na_position=, ignore_index=)
import pandas as pd
rich_set = pd.read_csv('TopRichestInWorld.csv', usecols=['Name']).squeeze()
#데이터 값 정렬
rich_set.sort_values() #이름이 A-Z순으로 오름차순
rich_set.sort_values(axis=0, ascending=False)
'''
axis(축)
-정렬에 사용할 축을 지정합니다.
-default가 0입니다.
-Series는 1차원 데이터라 축이 1개라서 의미가 없습니다.
-DataFrame은 2차원 데이터라 축이 2개입니다. 여기서는 활용됩니다.
ascending
-오름차순(True), 내림차순(False)로 지정합니다.
-default는 오름차순(True)입니다.
'''
rich_set.sort_values(ascending=True, kind='quicksort', na_position='last')
'''
kind
-정렬에 사용할 정렬 알고리즘을 지정합니다.
-특이한 상황이 아닌 경우 quicksort가 우수한 성능을 보입니다.
-그래서 default는 quicksort입니다.
na_position
-NaN값을 어디로 배치할지 정합니다.
-default는 뒤쪽으로 배치하기위해 'last'입니다.
'''
rich_set.sort_values(ascending=True, kind='quicksort', na_position='last'
,ignore_index =True)
'''
ignore_index
-정렬할 때 index열도 같이 정렬할 건지(False), 유지하고 정렬할 건지(True)를 지정합니다.
-default는 False입니다.
'''
Series - 값 정렬(inplace=, 비파괴적vs파괴적)
'''
비파괴적 처리
-원본 데이터가 파괴되지 않는다.
-저장할 땐 변수 = 원본.메소드() 와 같은 문법을 사용한다.
-파이썬 기본 함수에서도 이런 처리를 볼 수 있다.
'''
numbers = [1, 9, 3, 6, 7]
sorted(numbers) #[1, 3, 6, 7, 9]
# 원본 조회
numbers #[1, 9, 3, 6, 7]
user = "spencer"
user.replace('e', 'A') #'spAncAr'
# 원본 조회
user #'spencer'
#때문에 비파괴적인 처리 결과를 저장하려면 다음과 같이 해야한다.
numbers = [1, 9, 3, 6, 7]
numbers = sorted(numbers)
numbers #[1, 3, 6, 7, 9]
user = "spencer"
user = user.replace('e', 'A')
user #'spAncAr'
'''
파괴적 처리
-원본 데이터가 파괴된다.
-원본이 파괴되기 때문에 굳이 변수 = 원본.메소드()와 같은 문법을 사용하지 않는다.
-원본.메소드() 반환 값은 없거나, 있다면 주로 함수 실행 성공 여부(True/False)
또는 결과를 대략 파악할 수 있는 값이 반환된다.
-파이썬에선 대표적으로 .sort()가 있다.
sort_values의 Docstring 확인
inplace: 'bool' = False
-inplace=True를 주면 원본 데이터에 결과가 반영됩니다.
-[주의]복사본을 생성한 이후 사용할 것을 권고하고 있습니다. 최근 버전은 막혀져 있음
'''
# 하지만 무작정 사용하면 Error발생
rich_set.sort_values(inplace=True)
# 카피본 만들고 사용하기
rich_set_copy = rich_set.copy()
rich_set_copy.sort_values(inplace=True)
Series - 값 정렬(key=)
'''
key= -정렬 기준 지정
-정렬에 필요한 크고 작음의 기준을 정한다.
-글자라면 A-Z순, 숫자라면 크고 작음
-key인자에 함수를 지정하면되며, 잘 사용하려면 lambda에 익숙해야한다.
'''
basket = ['apple', 'Banana', 'Cherry', 'durian']
basket_series = pd.Series(basket)
# 그냥 sort_values()를 하면 문자부호 순서로 소문자가 무조건 밀려난다. (아스키코드 + 유니코드)
basket_series.sort_values()
# 만일 모두 대문자 또는 소문자라고 치고 정렬하려면?
basket_series.sort_values(key=lambda x:x.str.lower())
'''
.str.lower() 는 현재 시리즈의 값을 모두 문자열로 만든 다음 소문자로 변환하는 코드이다.
파이썬에서도 str()같은 함수를 지원하지만, pandas는 데이터를 변환하는 과정이 많다보니
map()함수처럼 데이터 각각 처리하고 + .함수.함수처럼 체인 형태의 코딩이 쉽도록 개선해놓는다.
'''
#현재 rich_set을 정렬하면 이름의 A-Z순으로 나온다.
rich_set.sort_values()
#이름 길이, 즉 문자열의 개수가 적고 많음 순으로 정렬
rich_set.sort_values(key=lambda x:x.str.len())
'''
단, lambda 인자에 들어오는 x값에 바로 len(x)나 lower(x)로 하면 에러가 난다.
왜냐하면 '각 데이터는 문자열(string)로 가져온 것'이 아닌 'Series'로 가져와집니다.
key=lambda x: x.str.len()에서 x에 담기는 데이터 유형은 Series이니 에러가 발생합니다.
'''
Series-인덱스 정렬(sort_index)
#.sort_index()은 인덱스 배열(색인 객체열)을 오름차순/내림차순으로 정렬한다.
rich_set.sort_index() #오름차순
rich_set.sort_index(ascending = False) #내림차순
'''
.sort_index() 인자는 왜 .sort_values()처럼 인자 종류가 많은 이유는
리스트의 인덱스라면 0과 자연수만 가능하지만
Pandas Series의 인덱스는 인덱스(색인 검색)의 기능이 부여됐을 뿐이며
값은 다양한 게 들어갈 수 있어서이다.
'''
Series - 값 세기(value_counts, sort=, ascending=, bins=, normalize=, dropna=)
import pandas as pd
# 나라 열만 가져오기 -> 시리즈 화
rich_country = pd.read_csv('TopRichestInWorld.csv', usecols=['Country/Territory']).squeeze()
# value_counts : collection.Counter와 비슷한 기능
rich_country.value_counts()
# 산업 열만 가져오기 -> 시리즈 화
rich_industry = pd.read_csv('TopRichestInWorld.csv', usecols=['Industry']).squeeze()
# 부자들이 가장 많이 하는 산업
rich_industry.value_counts()
'''
normalize
-퍼센트처럼 비중으로 계산합니다.
-미국이 36퍼센트, 중국이 17퍼센트
'''
rich_country.value_counts(normalize=False)
rich_country.value_counts(normalize=True)
'''
sort
-빈도별로 정렬
-False면 정렬이 안됨.
ascending
-True면 오름차순 정렬
-False면 내림차순
'''
# 부자로 가장 유니크한 산업을 찾는다면
rich_industry.value_counts(normalize=True, sort=True)
# 오름차순 정렬한다면
rich_industry.value_counts(normalize=True, ascending=True)
'''
bins
-개수를 입력하여, 그 만큼 구간을 나누어 카운트 합니다.
-bins가 지정안되면, 고유 값의 빈도로 카운드 합니다.
-숫자처럼 연속형 데이터만 가능합니다.
'''
# 나이 열만 가져오기 -> 시리즈 화
rich_age = pd.read_csv('TopRichestInWorld.csv', usecols=['Age']).squeeze()
rich_age.value_counts(bins=5)
rich_age.value_counts(bins=10)
'''
dropna
-카운트 시에 NaN형 데이터를 처리할지를 결정합니다.
-defalut True라서 None이 카운트가 되지 않다가
False시 None도 카운트가 된다.
'''
data = ['banana', None, 'apple', 'banana', 'apple']
data_set = pd.Series(data)
data_set.value_counts()
data_set.value_counts(dropna=False)
Series - 인덱스 위치 기반 조회(Access, indexing, slicing)
import pandas as pd
rich_set = pd.read_csv('TopRichestInWorld.csv')
rich_name = pd.read_csv('TopRichestInWorld.csv', usecols=['Name']).squeeze()
# 앞단 10개 조회
rich_name.head(10)
# 뒷단 10개 조회
rich_name.tail(10)
#특정 index 조회
rich_name[0]
rich_name[100]
# 범위를 넘기면 에러
rich_name[101]
#특정 Index들 조회
rich_name[[0,5,15]]
#인덱스 슬라이싱(Slicing)을 이용한 조회
rich_name[0:5]
# 슬라이스 숫자 생략도 파이썬처럼 가능
rich_name[:5]
# 0~50명단까지, 5배수에 해당하는 사람 이름을 조회하려면
rich_name[4:50:5]
Series - [참고] Index 주의사항 RangeIndex객체, Index객체
RangeIndex
- RangeIndex는 순차적인 정수로 구성된 인덱스 객체.
- 데이터프레임(DataFrame)이나 시리즈(Series)를 생성할 때, 명시적으로 인덱스를 지정하지 않은 경우에 기본적으로 생성되는 인덱스.
- RangeIndex는 0부터 시작하는 정수로 구성되며
- 일반적으로 데이터의 길이 또는 행의 개수에 따라 자동으로 생성
- RangeIndex는 변경할 수 없는(immutable) 객체로, 크기가 고정.
- RangeIndex는 메모리 사용을 최적화하여 데이터의 검색과 접근 속도를 향상합니다.
Index
- Index는 일련의 값으로 구성된 인덱스 객체.
- 문자열, 정수, 날짜 등 다양한 데이터 타입을 가질 수 있다.
- Index는 RangeIndex와 달리 명시적으로 지정되거나 다른 데이터의 인덱스로부터 생성될 수 있다.
- Index는 변경 가능한(mutable) 객체
- 따라서, 인덱스의 값이나 순서를 변경하거나 인덱스를 추가/삭제할 수 있다.
- Index는 데이터의 레이블링, 인덱싱, 슬라이싱 등 다양한 데이터 조작 작업에 활용된다.
RangeIndex vs Index 요약
- RangeIndex는 순차적인 정수로 구성되는 고정 크기의 인덱스 객체
- Index는 일련의 값으로 구성되며 변경 가능한 특성을 가진 인덱스 객체
- 두 객체 모두 데이터프레임이나 시리즈의 인덱스로 사용되고, 데이터 조작 및 접근을 위해 다양한 기능을 제공
del user_set['name']는 되고 del user_set[0]은 안 되는 이유
- del user_set['name'] : 인덱스 레이블을 사용하여 해당하는 인덱스와 값을 삭제하는 것
- del user_set[0] : 정수 인덱스를 사용하여 삭제하는 것이 불가능
정수 인덱스? 인덱스 레이블?
- 인덱스가 문자열일 경우 Series객체는 인덱스를 사용할 수 있다는 원칙이 있다.
- Series 객체는 인덱스 레이블 기준 연산이 우선된다.
삭제 연산은 레이블 접근만 허용
- 조회는 데이터를 파괴하지 않기에 정수 인덱스를 통한 방식도 허용하나
- del을 이용한 삭제는 인덱스 레이블 방식만 허용한다.
공부하며 어려웠던 내용
내용이 방대해서 과제를 풀어보며 차근차근 복습해야겠다.
'TIL' 카테고리의 다른 글
| Python 프로그래밍 및 Pandas 활용 실습(3)-2 (0) | 2024.01.04 |
|---|---|
| Python 프로그래밍 및 Pandas 활용 실습(3)-1 (2) | 2024.01.04 |
| Python 프로그래밍 및 Pandas 활용 실습(1) (1) | 2024.01.02 |
| 데이터 웨어하우스와 SQL 기본에 대해 배우고 이를 바탕으로 데이터 분석에 대해 학습(5) (1) | 2023.12.22 |
| 데이터 웨어하우스와 SQL 기본에 대해 배우고 이를 바탕으로 데이터 분석에 대해 학습(4) (0) | 2023.12.21 |