본문 바로가기

Python

[데이터 분석] 3주차 강의노트 (1) 데이터프레임

목표

  • 데이터프레임 사용법 익히기
  • 파이썬 이용해 데이터를 차트로 시각화
  • 상관 관계 분석 이해
  • 순서를 잘 파악하자. 각 과정이 유기적으로 연결된다는 걸 알아두기

 

데이터 프레임 형태 파악하기

- 판다스는 url 입력으로도 데이터를 바로 읽을 수 있음

- csv 파일을 데이터 프레임으로 읽을 때는 pd.read_csv(url, 세퍼레이터) 함수를 사용

import pandas as pd
url = 'https://raw.githubusercontent.com/justmarkham/DAT8/master/data/drinks.csv'
drink_df = pd.read_csv(url, ',')

- read.tabel과 pd.read_csv() 둘 다 같은 기능!

- type : 어떤 형태로 이뤄진 파일인지 확인 -> type(drink_df)

- 데이터프레임의 형태를 파악 -> drink_df.head(5) / drink_df.tail(6) / drink_df.sample(10)

- index : 데이터프레임의 인덱스를 확인하는 방법 -> df.index

RangeIndex(start=0, stop=193, step=1)

-> 193에서 stop한다는 것은 193은 포함하지 않는다는 의미. 즉, 0번부터 192번까지의 샘플이 있는 셈이므로 총 샘플의 수는 193개

**파이썬의 데이터 프레임은 0부터 시작하고, R은 1부터 시작함. 해석에 주의해야 함!

- dtypes : 데이터 프레임 내의 각각의 열의 타입을 확인하는 방법 -> drink_df.dtypes

country                          object   #object 자료형
beer_servings                     int64   #integer 정수형
spirit_servings                   int64   
wine_servings                     int64
total_litres_of_pure_alcohol    float64   #float 실수형. 소수점까지 표시.
continent                        object

- shape : 데이터 프레임의 행과 열의 개수 출력 -> drink_df.shape = (193.6) -> 193개 행과 6개 열
- values : 데이터 프레임 형태를 Numpy 행렬 형태로 변환해 출력 -> drink_df.values

Numpy를 쓰면 위의 데이터 프레임 행 형태가 아래의 리스트 타입으로 변환됨

array([['Afghanistan', 0, 0, 0, 0.0, 'AS'],
       ['Albania', 89, 132, 54, 4.9, 'EU'],
       ['Algeria', 25, 0, 14, 0.7, 'AF'],
       ...,
       ['Yemen', 6, 0, 0, 0.1, 'AS'],
       ['Zambia', 32, 19, 4, 2.5, 'AF'],
       ['Zimbabwe', 64, 18, 4, 4.7, 'AF']], dtype=object)

 

-> 이 상태에서 변환한 데이터의 첫번째 행을 출력하면 0번 인덱스로 접근하게 됨.

drink_df.values[0]  #0번 인덱스 출력

array(['Afghanistan', 0, 0, 0, 0.0, 'AS'], dtype=object)  #출력값

**for문으로도 같은 결과값을 얻을 수 있음

# 각 원소를 순차적으로 꺼내서 출력. 'element' 자리에 아무거나 들어가도 상관 없음
for element in drink_df.values[0]:
  print(element)
  
Afghanistan  #결과값
0
0
0
0.0
AS

 

데이터 프레임 열에 접근

1) 데이터프레임 이름.해당 열의 이름

#beer_servings 열에 접근하기. 
drink_df.beer_servings

 

2) 데이터프레임 이름['해당 열의 이름']

drink_df['beer_servings']
#결과값
0        0
1       89
2       25
3      245
4      217
      ... 
188    333
189    111
190      6
191     32
192     64
Name: beer_servings, Length: 193, dtype: int64

- 이런 식으로 하나의 열만 불러오면 2차원 테이블 형태의 데이터 테이블이 아니라, 판다스(Pandas)에서 제공하는 또 다른 데이터 타입인 '시리즈(Series)'가 됨.

- 컬럼 타입 확인해보면?

type(drink_df.beer_servings) #데이터 타입 확인하는 함수

pandas.core.series.Series #Series라고 나옴!

 3) 다수의 열에 접근하기 : 데이터프레임의 이름[['특정열 이름1', '특정열 이름2']]

drink_df[['beer_servings','wine_servings']] #대괄호 두 개!!

- 이렇게 뽑으면 두 개의 열만 있는 데이터 프레임이 출력됨. 얘는 파이썬의 리스트 형태!

- 따라서 리스트 형태로 열의 이름을 나열한 뒤에 '데이터프레임 이름[열의 이름이 나열된 파이썬 리스트]'를 해도 동일한 결과값이 나옴

cols = ['beer_servings','wine_servings']  #두 개의 열을 하나의 데이터프레임(리스트)로 만들기
drink_df[cols] #리스트 출력

 

데이터프레임의 정보 얻기

- 종합적인 정보를 볼 때는 info 함수 활용 -> drink_df.info()

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 193 entries, 0 to 192
Data columns (total 6 columns):
 #   Column                        Non-Null Count  Dtype  
---  ------                        --------------  -----  
 0   country                       193 non-null    object 
 1   beer_servings                 193 non-null    int64  
 2   spirit_servings               193 non-null    int64  
 3   wine_servings                 193 non-null    int64  
 4   total_litres_of_pure_alcohol  193 non-null    float64
 5   continent                     170 non-null    object 
dtypes: float64(1), int64(3), object(2)
memory usage: 9.2+ KB

- 머신 러닝 용어로는 데이터를 파악하기 위한 열(column)을 '특성(feature)'이라고 부름

-> 이 데이터 프레임에는 6개의 특성(country, beer_servings...)이 있음

- Non-Null Count는 결측치를 제외한 데이터의 개수 

-> continent 열에는 23개의 결측치가 있다는 의미

 

Null 결측 데이터 파악하기

- isnull().sum() : 해당 데이터프레임의 각 열에서 결측치(Null)이 총 몇 개인지 출력

- info함수로 구한 정보와 동일. 같은 값을 구하기 위해 여러 코드를 사용할 수 있다.

print(drink_df.isnull().sum()) #Null 총 개수 구한 걸 출력

country                          0
beer_servings                    0
spirit_servings                  0
wine_servings                    0
total_litres_of_pure_alcohol     0
continent                       23
dtype: int64

결측치 제거하기

- 데이터프레임 이름.dropna() -> drink_df.dropna()

- 빈 데이터가 소실되면서 행의 개수가 193개에서 170개로 줄어듦

 

한 번에 데이터 파악하기

- 데이터프레임 이름.describe()

  • 데이터프레임의 총 데이터의 수(count)
  • 평균(mean)
  • 표준편차(std)
  • 최소값(min)
  • 최대값(max)
  • 분위수(25%, 50%, 75%)에 해당하는 지점 **중간값 구할 때 median 썼던 것처럼!

- describe 함수는 숫자 정보만 계산해서 문자열 타입의 데이터는 빈칸으로 나옴

drink_df.describe() 의 출력값

- 특정 열의 정보 구할 때는 데이터프레임 이름.특정 열 이름.describe()

#beer_servings 열에 대한 정보만 출력하기
drink_df.beer_servings.describe()

count    193.000000
mean     106.160622
std      101.143103
min        0.000000
25%       20.000000
50%       76.000000
75%      188.000000
max      376.000000
Name: beer_servings, dtype: float64

- 특정 열의 각 항목들(최소값, 최대값, 총 개수 등등)만 따로 구하려면 describe 위치에 구하려는 것의 영어를 쓰면 됨

# beer_servings의 평균
drink_df.beer_servings.mean()
# beer_servings의 최대값
drink_df.beer_servings.max()
# 총합
drink_df.beer_servings.sum()
# 데이터 개수
drink_df.beer_servings.count()

 

원하는 데이터 찾기

1. 조건부 로직

- 데이터프레임의 이름.특정 열의 이름 == '특정값'

drink_df.continent == 'EU'

0      False
1       True
2      False
3       True
4      False
       ...  
188    False
189    False
190    False
191    False
192    False
Name: continent, Length: 193, dtype: bool

- 해당 조건을 만족하면 True, 만족하지 않으면 False. 

- 여기서 True인 행만 뽑아내고 싶으면 데이터프레임의 이름[True와 False로 구성된 시리즈]

drink_df[drink_df.continent=='EU'].head(20) #head 빼면 다 뽑힘

-> 데이터 프레임에서 continent의 값이 'EU'인 경우만을 필터링해서 뽑은 것

 

ex. beer_servings의 값이 158보다 큰 경우로 필터링해서 데이터프레임 뽑기

drink_df[drink_df['beer_servings'] > 158] #drink_df데이터프레임 안에 있는 beer_servings의 값이 158보다 큰 경우만 뽑기
drink_df[drink_df.beer_servings > 158] #특정 열만 뽑아내는 두 가지 방법 적용

 

조건 + 특정 열 몇 개만 출력

- 열 몇 개만 뽑는 방법 : 데이터프레임의 이름[['특정 열의 이름1, '특정 열의 이름2]]

- beer_servings의 값이 10 이하인 country, beer_servings 두 개 열 뽑아내기

drink_df[drink_df.beer_servings <= 10][['country','beer_servings']]

 

조건으로 필터링해서 얻은 시리즈의 정보값 구하기

ex1.

# continent값이 EU인 beer_servings 열(시리즈)의 평균 구하기
drink_df[drink_df.continent=='EU'].beer_servings.mean()

ex2.

# beer_servings값이 beer_servings열의 평균값보다 행만 뽑아내기
drink_df[drink_df.beer_servings > drink_df.beer_servings.mean()]

 

특정 열에 Null 값이 있는 경우만 뽑아내기

drink_df[drink_df.continent.isnull()]

 

continent의 값에 NaN값인 경우만 출력됨

- 다른 열에는 값이 존재하지만 continent 열에는 값이 없는 경우

 

2. AND, OR, NOT 연산자

x or y x와 y 둘 중에 하나만 참이어도 참이다 조건1 & 조건2
x and y x와 y 모두 참이어야 한다 조건1 | 조건2
not x x가 거짓이면 참이다 ~ 조건 (조건을 만족하는 경우의 반대. 즉, 조건을 만족하지 않는 경우)

ex1. not 조건

# continent의 값이 'EU'가 아닌 경우만 필터링
drink_df[~(drink_df.continent == 'EU')]

ex2. and 조건

# continent의 값이 EU이면서 wine_servings의 값이 300보다 큰 경우
drink_df[(drink_df.continent=='EU') & (drink_df.wine_servings > 300)]

- 두 가지 조건 모두 만족하는 행은 193개 행 중 단 3개. 

- and를 or로 바꾸면 둘 중 하나라도 만족하는 행 출력

-> 이 경우 만족하는 행이 45개

**만족하는 행의 개수 구하는 함수는 len()

# OR 조건을 적용했을 때 행의 길이 출력
len(drink_df[(drink_df.continent=='EU') | (drink_df.wine_servings > 300)])

 

로직과 수치 정보의 결합

  • drink_df에서 total_litres_of_pure_alchohol 값이 최대값인 경우의 country 열 출력하기

- 특정 열의 최대값을 구하기 : 데이터프레임 이름.특정 열의 이름.max()

- 특정 열만을 출력하기 : ['특정 열의 이름'] 또는 .특정 열의 이름

drink_df[drink_df.total_litres_of_pure_alcohol == drink.df.total_litres_of_pure_alcohol.max()]['country']
  • drink_df에서 wine_servings의 값이 300보다 크거나, beer_servings의 값이 300보다 크거나, spirit_servings의 값이 300보다 큰 경우의 contry열 데이터를 모두 카운트했을 때 숫자를 출력하기

- 다수의 조건을 '또는'으로 한 번에 정리 : 데이터 프레임.[(특정 열에 대한 조건1) | (조건2)] 

- 조건에 해당하는 열의 개수 구하기 : len() 또는 count()

#count 함수 사용
drink_df[(drink_df.wine_servings >300)|(drink_df.beer_servings >300)|(drink_df.spirit_servings >300)].country.count()

#len 함수 사용
len(drink_df[(drink_df.wine_servings >300)|(drink_df.beer_servings >300)|(drink_df.spirit_servings >300)].country)

 

정렬하기

- 데이터프레임의 이름.sort_values('정렬 기준이 되는 열의 이름')

# beer_servings을 기준으로 정렬
drink_df.sort_values('beer_servings')

- 디폴트는 오름차순

- 내림차순으로 정렬하려면 sort_values의 인자로 ascending=False를 추가

-> 데이터프레임의 이름.sort_values('정렬 기준이 되는 열의 이름', ascending=False)

 

- 여러 기준으로 정렬할 경우 열의 이름들을 원소로 하는 리스트를 sort_values의 입력으로 사용하면 됨

# 2개의 열을 기준으로 정렬
drink_df.sort_values(['beer_servings', 'wine_servings'])

-> 앞에 명시한 열을 기준으로 우선적으로 먼저 정렬하고 뒤의 기준으로 다시 정렬