파이썬/Pandas

2.Pandas - DataFrame - 1

잘잔디 2023. 5. 2. 09:11

DataFrame

  • 2차원 array에 index값을 붙인 형태와 비슷하다.
  • 행 index 뿐만 아니라 열 index도 따로 지정이 가능하다.
  • 데이터프레임은 전치(transpose)를 포함하여 2차원 array가 가지는 대부분의 속성이나 메서드를 지원한다.
  • 산술연산은 row와 column 모두 적용된다.
  • series 객체를 갖는 dictionary라고 이해해도 된다.

DataFame 생성

  1. 하나의 열이 되는 데이터를 리스트나 일차원 배열을 준비한다.
  2. 각각의 열에 대한 이름(label)을 키로 가지는 dictionary를 만든다
  3. 이 데이터를 DataFrame 클래스 생성자에 넣는다. 동시에 열 방향 index는 columns 인수로 행방향 index는 index인수로 지정한다.
data = {
    "빨강": ['ff3399', 'ff1999', 'f5007a', 'ff1493'],
    "노랑": ['ffe536', 'ffff00', 'ffd700', 'ebd64a'],
    "초록": ['36ffb4', '1dffba', '00f79b', '00fa9a'],
    "파랑": ['003dfd', '4682b4', '00bcf8', '148cb2'],
    "가격": [1000.0,1000.0,1000.0,1000.0]
}
color_pen = pd.DataFrame(data,index=range(1,5) ) # columns에는 data의 key 값들이 들어가게 된다.
color_pen.name = "형광펜색"
color_pen.index.name = '순서'
color_pen.columns.name = '색'
print(color_pen)
print(color_pen.name)

data = {
    "2015": [9904312, 3448737, 2890451, 2466052],
    "2010": [9631482, 3393191, 2632035, 2431774],
    "2005": [9762546, 3512547, 2517680, 2456016],
    "2000": [9853972, 3655437, 2466338, 2473990],
    "지역": ["수도권", "경상권", "수도권", "경상권"],
    "2010-2015 증가율": [0.0283, 0.0163, 0.0982, 0.0141]
}
columns = ["지역", "2015", "2010", "2005", "2000", "2010-2015 증가율"]
index = ["서울", "부산", "인천", "대구"]
df = pd.DataFrame(data, index=index, columns=columns)

df

지역     2015     2010     2005     2000     2010-2015     증가율

서울 수도권 9904312 9631482 9762546 9853972 0.0283
부산 경상권 3448737 3393191 3512547 3655437 0.0163
인천 수도권 2890451 2632035 2517680 2466338 0.0982
대구 경상권 2466052 2431774 2456016 2473990 0.0141
df.values

df.columns

df.index

# index와 column에 이름을 붙이는 것도 가능하다 
df.index.name = "도시"
df.columns.name = "특성"
df

특성     지역     2015     2010     2005     2000     2010-2015      증가율

도시            
서울 수도권 9904312 9631482 9762546 9853972 0.0283
부산 경상권 3448737 3393191 3512547 3655437 0.0163
인천 수도권 2890451 2632035 2517680 2466338 0.0982
대구 경상권 2466052 2431774 2456016 2473990 0.0141

DataFrame 전치도 가능하다

df.T

서울     부산     인천     대구

지역 수도권 경상권 수도권 경상권
2015 9904312 3448737 2890451 2466052
2010 9631482 3393191 2632035 2431774
2005 9762546 3512547 2517680 2456016
2000 9853972 3655437 2466338 2473990
2010-2015 증가율 0.0283 0.0163 0.0982 0.0141
df.T
df['2005-2010 증가율'] = ((df['2010']-df['2005']) / df['2005']*100).round(3) #갱신
del df['2010-2015 증가율'] #삭제
df

지역     2015     2010     2005     2000     2005-2010     증가율

서울 수도권 9904312 9631482 9762546 9853972 -1.343
부산 경상권 3448737 3393191 3512547 3655437 -3.398
인천 수도권 2890451 2632035 2517680 2466338 4.542
대구 경상권 2466052 2431774 2456016 2473990 -0.987

열 인덱싱

  • column label을 key로 인덱싱이 가능하다.
  • 인덱싱한 type은 Series이다.
  • label을 배열 또는 여러 개의 열을 indexing 하면 DataFrame type이 된다.
  • 만약 하나의 열만 빼내면서 데이터프레임 자료형을 유지하고 싶다면 원소가 하나인 리스트를 써서 인덱싱 하면 된다.
  • column index가 문자열 label인 경우에는 순서를 나타내는 정수 index를 column인덱싱에 사용할 수 없다.
  • 원래부터 정수형 column index를 가지는 경우에는 index값으로 정수를 사용할 수 있다.
print(df)

print(df['2010'] , type(df['지역']),sep="\\n")# series type

print(df[['2010','2005']], type(df[['2010','2005']]),sep="\\n") # DataFrame type

print(df[['2010']], type(df[["2010"]]),sep='\\n') #DataFrame type
# print(df[0]) #얘는 에러가 난다.

DataFrame row 슬라이싱

  • row 단위로 인덱싱을 하고자 하면 항상 슬라이싱을 해야한다.
  • idnex값이 문자 label이라면 label 슬라이싱도 가능하다.
print(df[:1]) # 서울은 df에서 index가 '서울' 이자 0 이다.

print(df[:'서울'], type(df[:'서울']),sep = "\\n") #반환 type은 DataFrame이 된다.

개별 데이터 인덱싱

  • DataFrame에서 열 라벨로 시리즈를 인덱싱 하고 이를 다시 행 라벨로 인덱싱 하면 개별 데이터가 나온다.
  • 반대순서로 인덱싱을 짜면 KeyError가 발생한다. 행 라벨 인덱싱은 무조건 DataFrame형태로 데이터가 나오기 때문임.

 

df['2015']['서울']

 

DataFrame 인덱싱정리사진

### 연습문제1

data = {
    "국어": [80, 90, 70, 30],
    "영어": [90, 70, 60, 40],
    "수학": [90, 60, 80, 70],
}
columns = ["국어", "영어", "수학"]
index = ["춘향", "몽룡", "향단", "방자"]
df = pd.DataFrame(data, index=index, columns=columns)

# 방자의 영어값을 바꾸고 평균을 구해라
df['영어']['방자'] = 80
df['평균'] = ((df['국어']+df['영어']+df['수학'])/3).round(2)
print(df)

# '향단' 의 점수를 Series 형태로 출력해라 (그냥 행 slicing하면 DataFrame type임.)
ser = pd.Series([df['국어']['향단'],df['영어']['향단'],df['수학']['향단'],df['평균']['향단']],index =['국어','영어','수학','평균'])
ser.name = '향단'
print(ser)
print(df.T['향단'])
print(type(df.T['향단']))

# 연습문제 2
import numpy as np
np.random.seed(0)
value = np.random.randn(6,4)
pd.DataFrame(value,index = pd.date_range("20130226",periods=6),columns =list('ABCD') )

A     B     C     D

2013-02-26 1.764052 0.400157 0.978738 2.240893
2013-02-27 1.867558 -0.977278 0.950088 -0.151357
2013-02-28 -0.103219 0.410599 0.144044 1.454274
2013-03-01 0.761038 0.121675 0.443863 0.333674
2013-03-02 1.494079 -0.205158 0.313068 -0.854096
2013-03-03 -2.552990 0.653619 0.864436 -0.742165

Pandas 데이터 입출력

  • Pandas는 데이터 파일을 읽어 DataFrame을 만들 수 있습니다.
  • CSV 파일 포맷은 데이터 값이 comma(,)로 구분되는 텍스트 파일입니다.
  • pandas.DataFrame.to_csv()로 사용하며 DataFrame을 csv파일로 만든다.
  • pandas.read_csv()로 csv파일을 읽어올 수 있다.
  • index는 쓸모없기 때문에 생략할 수 있는 인자가 있다.(index = False)
  • header가 False이면 column인덱스가 없어지고, 첫 값들이 column이 된다(header = False)
  • 불러올 때 names=[컬럼인덱스들] 을 사용하여 column인덱스를 불러올때 추가가 가능하다.

value_dict = {
    'c1':[1,2,'누락'],
    'c2': [1.11,'',3.33],
    'c3': ['one','two','three']
}
df_csv = pd.DataFrame(value_dict)
df_csv

 

df_csv.to_csv('csv_example.csv',index=False)
df_read = pd.read_csv('csv_example.csv') # 불러올 떄 index가 자동으로 0,1,2로 할당됨을 볼 수 있다.
df_read

c1     c2     c3

0 1 1.11 one
1 2 NaN two
2 누락 3.33 three
df_csv.to_csv('csv_example2.csv',index = False, header = False)
pd.read_csv('csv_example2.csv',names=['c0','c1','c2'])

c0     c1     c2

0 1 1.11 one
1 2 NaN two
2 누락 3.33 three

콤마가 아니라 공백으로 구분됨 텍스트 파일에 대한 처리

  • 주피터 랩 매직 명령어 사용하여 파일 저장이 가능하다.

%%writefile 파일명

  • 구분자가 comma로 정해진 게 아니라면 공백이 구분자인 경우에는 ‘+’ 정규식 문자열을 사용하면 된다.
%%writefile sample3.txt
c1        c2        c3        c4
0.179181 -1.538472  1.347553  0.43381
1.024209  0.087307 -1.281997  0.49265
0.417899 -2.002308  0.255245 -1.10515

pd.read_table('sample3.txt',sep='\\s+')

c1     c2     c3     c4

0 0.179181 -1.538472 1.347553 0.43381
1 1.024209 0.087307 -1.281997 0.49265
2 0.417899 -2.002308 0.255245 -1.10515

파일 안을 살펴봤을 때 데이터뿐만 아니라 부과적인 설명이 있는 경우의 처리

  • skiprows=[]
  • 리스트가 아닌 range를 써도 된다.
%%writefile sample4.txt
파일 제목: sample4.txt
데이터 포맷의 설명: 흠..
c1, c2, c3
1, 1.11, one
2, 2.22, two
3, 3.33, three

pd.read_csv('sample4.txt',skiprows=[0,1]) #0,1번째줄은 건너뛰고 읽는다!
pd.read_csv('sample4.txt',skiprows=range(2))

c1     c2     c3

0 1 1.11 one
1 2 2.22 two
2 3 3.33 three
3 # sample4.txt 만드는 과정. NaN NaN

데이터로 불러올 자료 안의 특정값을 NaN으로 취급하고 싶은 경우

  • na_values인수에 NaN값으로 취급할 값을 넣습니다
df_na_val = pd.read_csv('csv_example.csv',na_values=['누락'])
df_na_val

c1     c2     c3

0 1.0 1.11 one
1 2.0 NaN two
2 NaN 3.33 three

파일 출력(저장) 시에 sep 인수로 구분자 변경 가능

df_na_val.to_csv('sample5.txt',sep='|')

Pandas 데이터 csv로 출력(저장)하기

  • 저장할 때도 na_rep 키워드 인수를 사용하여 NaN 표시값을 바꿀 수 있다.
df_na_val.to_csv('sample6.csv',na_rep='누락')

온라인의 csv 파일 가져오기

  • read_csv 명령 사용 시 path 대신 URL을 지정하면 Pandas가 직접 해당 파일을 다운로드하여 읽어 들인다.
  • head() , tail()로 전체 파일 중 부분을 가져올 수 있다.
titanic = pd.read_csv('<https://storage.googleapis.com/tf-datasets/titanic/train.csv>')
titanic.head(5)

survived sex age n_siblings_spouses parch fare class deck embark_town alone

0 0 male 22.0 1 0 7.2500 Third unknown Southampton n
1 1 female 38.0 1 0 71.2833 First C Cherbourg n
2 1 female 26.0 0 0 7.9250 Third unknown Southampton y
3 1 female 35.0 1 0 53.1000 First C Southampton n
4 0 male 28.0 0 0 8.4583 Third unknown Queenstown y