|Playdata_study/Python

210722_Pandas (DataFrame)

케리's 2021. 7. 23. 11:26

DataFrame 생성

 

DataFrame은 2차원 배열 형식
표와 같은 스프레드 시트 자료 구조 (엑셀과 비슷)
여러개의 컬럼을 가지며 서로 다른 종류의 값(?)이 담긴다.

 

 

 

DataFrame 생성하는 방법

 

  • 리스트 값을 딕셔너리로 사용
  • Numpy 배열을 이용
  • read_csv, read_excel(),,, 함수사용

 

import numpy as np
import pandas as pd
from pandas import DataFrame,Series
import matplotlib.pyplot as plt

 

 

 

#  딕셔너리로 데이터 프레임 생성

 


딕셔너리의 key가 데이터 프레임의 column 값으로 들어간다?
여러 개의 컬럼을 가지면서 서로 다른 시리즈의 값이 담긴다.

중요!!! state, year, pop 는 각각의 series 이다
즉, 데이터프레임은 series의 결합체이다.
Series는 ndarray 클래스 타입으로 동일한 자료형이 요구된다.

 

 

# 1. 딕셔너리로 데이터 프레임 생성

'''
딕셔너리의 key가 데이터 프레임의 column 값으로 들어간다?
여러 개의 컬럼을 가지면서 서로 다른 시리즈의 값이 담긴다.

중요!!! state, year, pop 는 각각의 series 이다
즉, 데이터프레임은 series의 결합체이다.
Series는 ndarray 클래스 타입으로 동일한 자료형이 요구된다.

'''

dic = {'state' : ['Ohio','Ohio','Ohio','Nevada','Nevada','Nevada'],
        'year' : [ 2000,  2001,  2002,   2001,    2002,    2004],
        'pop'  : [ 1.5 ,  1.7,    3.6,    2.4,     2.9,     3.2]
       } # value 값을 list

dicDf = DataFrame(dic) # 위치 매개변수
dicDf

 

print(dicDf.state)
print(type(dicDf.state))
print('*' * 50)

print(dicDf.year)
print(type(dicDf.year))
print('*' * 50)


# pop 함수가 적용될 수 있으니 아래와 같이 사용하도록 하자

#print(dicDf.pop)
#print(type(dicDf.pop)) 

'''
<bound method DataFrame.pop of     state  year  pop
0    Ohio  2000  1.5
1    Ohio  2001  1.7
2    Ohio  2002  3.6
3  Nevada  2001  2.4
4  Nevada  2002  2.9
5  Nevada  2004  3.2>
<class 'method'>
'''



print(dicDf['pop'])
print(type(dicDf['pop']))

=========================================================

0      Ohio
1      Ohio
2      Ohio
3    Nevada
4    Nevada
5    Nevada
Name: state, dtype: object
<class 'pandas.core.series.Series'>
**************************************************

0    2000
1    2001
2    2002
3    2001
4    2002
5    2004
Name: year, dtype: int64
<class 'pandas.core.series.Series'>
**************************************************

0    1.5
1    1.7
2    3.6
3    2.4
4    2.9
5    3.2
Name: pop, dtype: float64
<class 'pandas.core.series.Series'>

 

 

1. 딕셔너리로 생성

 

data1 = {
    'name' : ['James', 'Peter', 'Tomas', 'Robert'],
    'address' : ['NY', 'TEXAS', 'LA', 'TEXAS'],
    'age' : [33, 44, 55, 66]
}

df1 = DataFrame(data1)
df1

 

 

 

2. Numpy배열 Data로 생성

 

 

위치 매개변수와 키워드 매개변수를 사용
()안에 data, index, column 입력가능 
data, index, column = 값, 이것을 keyword 매개변수라고한다

DataFrame은 2차원으로 만들어야함 (reshape사용)

 

# 위치 매개변수와 키워드 매개변수를 사용
# ()안에 data, index, column 입력가능 
# data, index, column = 값, 이것을 keyword매개변수라고한다

# DataFrame은 2차원으로 만들어야함 (reshape사용)
np.random.seed(100)
df2 = DataFrame(np.random.randint(10,100,16).reshape(4,4), #위치 매개변수
               index = list('abcd'),
               columns = list ('abcd')
               )
df2

 

 

# 컬럼명 수정 

 

# 컬럼명을 수정
df2.columns = ['one', 'two', 'three', 'four']
df2

 

 

 

3. read_csv() 함수로 생성

 

 csv 파일을 읽어들여서 생성 csv(comma-separated values)

 

df3 = pd.read_csv('../data/tips.csv')
df3

 

 

 

DataFrame 구조

 

 

1. 구조를 확인하는 속성

 

  • index
  • columns
  • values
  • dtypes → s를 붙여야한다!
  • info()
  • shape : 몇 행 몇열인지

 

 

 

# index

 

print(df3.index)

===============================

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

 

# columns

 

print(df3.columns)

========================

Index(['total_bill', 'tip', 'sex', 'smoker', 'day', 'time', 'size'], dtype='object')

 

# values

 

print(df3.values)

===========================================

[[16.99 1.01 'Female' ... 'Sun' 'Dinner' 2.0]
 [10.34 1.66 'Male' ... 'Sun' 'Dinner' 3.0]
 [21.01 3.5 'Male' ... 'Sun' 'Dinner' 3.0]
 ...
 [17.82 1.75 'Male' ... 'Sat' 'Dinner' 2.0]
 [18.78 3.0 'Female' ... 'Thur' 'Dinner' 2.0]
 [25.34 nan nan ... nan nan nan]]

 

# dtypes

 

print(df3.dtypes)
# dtype 이 안되는 이유는 series의 결합체라서 되지 않음

======================================================

total_bill    float64
tip           float64
sex            object
smoker         object
day            object
time           object
size          float64
dtype: object

 

# info()

 

# 전체적인 dataframe에 column 대한 디테일한 정보
# 컬럼의 타입을 확인하고, info를 써서 한번에 null값이 존재하는지 (누락데이터가 존재하는지)먼저 확인하기 위해
# 분석 전에 info() 를 사용한다.

print(df3.info())

===========================================

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 245 entries, 0 to 244
Data columns (total 7 columns):
 #   Column      Non-Null Count  Dtype  
---  ------      --------------  -----  
 0   total_bill  245 non-null    float64
 1   tip         244 non-null    float64
 2   sex         244 non-null    object 
 3   smoker      244 non-null    object 
 4   day         244 non-null    object 
 5   time        244 non-null    object 
 6   size        244 non-null    float64
dtypes: float64(3), object(4)
memory usage: 13.5+ KB
None

 

 

 # T는 Transpose 의 약자, 행과 열을 바꿔준다.

 

print(df1.T) # T는 Transpose 의 약자, 행과 열을 바꿔준다!

==================================

             0      1      2       3
name     James  Peter  Tomas  Robert
address     NY  TEXAS     LA   TEXAS
age         33     44     55      66

 

df1 원본 df파일

 

 

 

 

 

2. 조회를 확인하는 함수

 

  • info()
  • head() : 앞 쪽 조회
  • tail() : 뒷 쪽 조회

 

 

 

# head()

 

df3
df3.head() # 앞에서 5줄만 가져온다
# df3.head(5), 위랑 같은 결과

 

df3.head(1) # 가져오고 싶은 숫자를 적는다

 

 

# shape

 

print(df3.shape) # 행과 열을 나타냄

====================================

(245, 7)

 

 

# tail()

 

df3.tail() # 뒤에서 5줄만 가져온다

 

 

DataFrame - 컬럼명 변경 및 추가하기

 

원본이 바로 변경되는 옵션과 원본이 변경되지 않는 옵션이 존재한다.

 

  • 컬럼명 전체 수정 : columns  ---> 원본 바로 변경
  • 컬럼명 부분 수정 : rename  ---> 원본 변경 되지 않음

 

 원본 데이터를 변경하려면 새로운 옵션을 하나 익혀야 한다.


   ★ inplace = True 를 추가 해야 한다.

 

 

 

1. 컬럼명 변경하기

 

df2

 

# 컬럼명 전체 변경하기 

# 1. 컬럼명 변경하기 (전체)
df2.columns = ['A-class', 'B-class', 'C-class', 'D-class']
df2

 

 

# 컬럼명 부분 변경하기 : rename

 

# 2. 컬럼명 변경하기 (부분)
# address -> addr
df1

df1 원본

 

# df1.rename(columns = {'address' : 'addr'}) # {'기존컬럼명':'새로운컬럼명'}

df1.rename(columns = {'address' : 'addr'}, inplace = True)
df1

 

 

2. 컬럼 추가하기

 

df1['phone'] = np.nan
df1

 

 

 

DataFrame - 데이터 검색하기

  • iloc
  • loc
  • at
  • iat

 

df2

 

 

df2.columns = ["one", "two", "three", "four"] # 다시 원래 컬럼으로 돌려놓았다
df2

 

 

슬라이싱 하는 방법


1) 정수형 슬라이싱
2) 라벨형 슬라이싱

 

 

1. row 데이터만 가져오겠다.

 

#   1) 정수형 슬라이싱
print(df2[0:2])

#   2) 라벨형 슬라이싱
print(df2['a':'b'])

======================================
   one  two  three  four
a   18   34     77    97
b   89   58     20    62
   one  two  three  four
a   18   34     77    97
b   89   58     20    62

 

 

2. column 지정 데이터 값 가져오기

 

#df2['one':'three'] # head값만 나옴
df2[['one','three']] # column 값

 

 

3. row를 가져오는데 특정 컬럼에 대한 row 가져오기 

 

print(df2[['two']])
print(df2[['two']] > 40)

=======================================

   two
a   34
b   58
c   76
d   25
     two
a  False
b   True
c   True
d  False

 

# iloc : 인덱스값을 선택해 원하는 값 가져옴

 

# iloc : 인덱스값을 선택해 원하는 값 가져옴
df2[df2['two'] > 40].iloc[:,1:2] # iloc [row, column]

 

df1

 

# 2,3번째 줄의 데이터를 iloc, loc로 가져와 보자

 

 

# iloc : 인덱싱으로 찾는방법 (가장 뒷자리 포함 안됨)
print(df1.iloc[1:3, 0:4])
print('*'*50)
print(df1.iloc[1:3, :4])
print('*'*50)
print(df1.iloc[1:3])
print('*'*50)

==========================================================
    name   addr  age  phone
1  Peter  TEXAS   44    NaN
2  Tomas     LA   55    NaN
**************************************************
    name   addr  age  phone
1  Peter  TEXAS   44    NaN
2  Tomas     LA   55    NaN
**************************************************
    name   addr  age  phone
1  Peter  TEXAS   44    NaN
2  Tomas     LA   55    NaN

 

 

# loc : 라벨명으로 찾는방법 (1:2모두포함)
print(df1.loc[1:2]) 
print('*'*50)
print(df1.loc[1:2,'name':'age'])

=================================================================

    name   addr  age  phone
1  Peter  TEXAS   44    NaN
2  Tomas     LA   55    NaN
**************************************************
    name   addr  age
1  Peter  TEXAS   44
2  Tomas     LA   55

 

 

# 스칼라 값 가져오기 iat, at

 

# iat

# 스칼라 값 가져오기 iat, at

print(df1.iloc[1:3])
print(df1.loc[1:2])
print('*'*50)
print(df1.iat[1,1])

=============================================

    name   addr  age  phone
1  Peter  TEXAS   44    NaN
2  Tomas     LA   55    NaN
    name   addr  age  phone
1  Peter  TEXAS   44    NaN
2  Tomas     LA   55    NaN
**************************************************
TEXAS

 

# at

# at 활용

# Tomas 나이 55세 출력
print(df1.at[2,'age'])
print('*'*50)

#Robert의 주소 TEXAS 출력 
print(df1.at[3,'addr'])

==============================================

55
**************************************************
TEXAS

 

 

# Tomas의 현재 나이가 55세, iat를 이용해서 Tomas의 나이를 50세로 변경하세요

 

df1.iat[2,2]=50
df1

 

 

# 5번째 row 추가, loc를 이용해서 , 값은 전부 누락데이터

 

# 5번째 row 추가, loc를 이용해서 , 값은 전부 누락데이터
df1.loc[4] = np.nan
df1

 

Data 삭제하기

  • drop()

 

# 마지막 row를 삭제한다

 

# 마지막 row를 삭제한다
df1.drop(4, inplace = True)

 

 

# phone에 해당하는 부분을 삭제하고 원본 반영

 

df1.drop('phone', axis =1, inplace = True)

 

 

DataFrame - 데이터 정렬하기

  • sort_index()
    orderby 와 같은의미, axis = 0 , 오름차순이 defalut값
  • sort_value()

 

df2

 

 

# sort_index()

 

df2.sort_index()

 

df2.sort_index(axis=1, ascending=False) # ascending 오름차순

 

df2.sort_values(by=['four'])

 

 

실전데이터로 응용하기

 

df3.head(3)

 

 

# 문제 1. tip 비율로 sort(많이 받은 팁이 윗쪽에 오도록), 샘플데이타 5개만

 

# 문제 1. tip 비율로 sort(많이 받은 팁이 윗쪽에 오도록), 샘플데이타 5개만

df3.sort_values(by=['tip'],ascending=False).head()

 

 

 

# Visualization

 

# Visualization

df3.sort_values(by=['tip'],ascending=False).head().plot(kind = 'bar')
plt.show()
# 숫자데이터만 표시, 성별,요일 표시되지 않음

 

 

# tip만 보는방법 

 

# tip만 보는방법 

df3.sort_values(by=['tip'],ascending=False).head()['tip'].plot(kind = 'bar')
plt.show()

 

 

# 문제 2. 요일별, tip별 정렬 각각 다르게 정렬
   day는 내림차순, tip은 오름차순
  마지막 데이타 7개만 디스플레이

 

# 문제 2. 요일별, tip별 정렬 각각 다르게 정렬
# day는 내림차순, tip은 오름차순
# 마지막 데이타 7개만 디스플레이

df3.sort_values(by=['day','tip'],ascending=[True,False]).tail(7)

 

 

중복 된 값을 배제하는 기능

  • unique()

 

df3['day']

=================================================

0       Sun
1       Sun
2       Sun
3       Sun
4       Sun
       ... 
240     Sat
241     Sat
242     Sat
243    Thur
244     NaN
Name: day, Length: 245, dtype: object

 

# unique()

df3['day'].unique()

=====================================

array(['Sun', 'Sat', 'Thur', 'Fri', nan], dtype=object)

 

 

 

# value_counts() : NaN은 count함수에서 제외된다.

 

df3['day'].value_counts() #NaN , count함수에서 제외된다.

==========================================

Sat     87
Sun     76
Thur    62
Fri     19
Name: day, dtype: int64

 

 

# isin() 특정한 데이타가 들어있는지 여부를 판단

 

df3['day'].isin(['Sat','Sun'])

===========================================

0       True
1       True
2       True
3       True
4       True
       ...  
240     True
241     True
242     True
243    False
244    False
Name: day, Length: 245, dtype: bool

 

 

# 문제 3. df3 데이터 프레임에서  목, 금요일에 해당하는 데이터만 추출

 

# 문제 3. df3 데이터 프레임에서  목, 금요일에 해당하는 데이터만 추출

# df3 # 전체데이터를 확인하고
# df3['day'].unique() # 어떤 요일이 존재하는지 모르기 때문에 중복제거를 한후 요일 확인하고

df3[df3['day'].isin(['Thur','Fri'])] #원하는 값 추출

 

 

# 문제4. isnull() 사용해서 컬럼별 누락데이터의 총 합을 출력

 

# 문제4. isnull() 사용해서 컬럼별 누락데이터의 총 합을 출력
# axis 값을 어떻게 부여하는 가에 따라서 결과가 완전히 달라진다!  중요!!
# df3.isnull().sum(axis=0)
df3.isnull().sum(axis=1)

========================================================

0      0
1      0
2      0
3      0
4      0
      ..
240    0
241    0
242    0
243    0
244    6
Length: 245, dtype: int64

 

 

df3.isnull().sum(axis=0).plot(kind='hist')