구조화 된 데이터의 처리를 지원하는 Python 라이브러리이다.
Pandas의 공식 GitHub의 설명은 아래와 같다.
"관계형" 또는 "레이블이 된" 데이터로 쉽고 직관적으로 작업할 수 있도록 설계되었고 빠르고 유연한 데이터 구조를 제공하는 Python 패키지
여기서 중요한 부분은 "관계형" 또는 "레이블이 된" 데이터라는 것이다.
Excel 데이터나 DBMS의 관계형 테이블 형태와 같은 표 형태의 데이터로 처리한다는 것이다.
Numpy와 통합하여 강력한 Spread Sheet 처리 기능을 제공하며, 주로 데이터 처리 및 통계 분석을 위해 활용한다.
하지만, Table 형태로 데이터를 저장하므로 음성이나 이미지 데이터를 다루는 데에는 그다지 적합하지는 않다.
단지, Text를 다루는 NLP 쪽에서는 매우 강력한 도구라고 할 수 있다.
Pandas에서 가장 많이 활용되는 2가지 개념을 뽑으라면 Seires와 DataFrame이 아닐까 싶다.
즉, 이 2가지만 제대로 알고 있어도 Pandas의 대부분 기능을 잘 활용할 수 있게 될 것이다.
아래 사진을 보자
위 사진이 Series와 DataFrame을 잘 설명한 것 같다.
Series란 Index가 존재하는(Indexing된) 데이터의 1차원 배열을 의미한다.
여기서 생각할 점은 저렇게 활용할 경우 ndarray를 활용하면 되는 것이 아닐까라는 생각이 들 수도 있다.
실제로 위 사진만 보면 apples Series의 0번째 값을 접근할 때 apples[0]으로 접근하면 될 것 같고, 이 경우 Numpy를 통해 Array를 형성했을 때의 결과와 같다고 생각이 될 수도 있다.
Series가 Numpy보다 강력한 점은, Index가 명시적이라는 것이다.
Ndarray를 생각해보자. 우리는 Index를 바꿀 수 없다. 만약 Index를 바꾸기 위해서는 Index에 존재하는 값을 교환하거나, Dict를 활용하여 Index를 추출한 뒤, Dict에서 Index를 검색하는 방법을 활용해야 한다.
하지만 Pandas의 Series를 활용하면 그럴 필요가 전혀 없다. index 자체가 명시적이기 때문에 굳이 0, 1,...으로 순차적으로 Indexing할 필요가 없을 뿐더러, int가 아닌 값으로도 Indexing이 가능하다.
따라서, 이런 중간 과정을 없앴다는 점에서 강력한 성능을 가진다고 할 수 있을 것이다.
1. Index 이름 중복 가능
Default Index은 [0,1,2,3,...]으로 Python List나 Ndarray의 Index와 동일하다.
하지만, 내가 원할 경우 Index를 [0,0,2,3,...] 처럼 지정해줄 수도 있다.
물론, 개인적인 생각으로 가능한 것과 활용성은 차이가 있다고 생각한다. 굳이 활용해야 할까? 싶은 기능이긴 하다
2. Index 이름 숫자 이외에도 지정 가능
나는 이 기능이 매우 매력적이라고 생각한다.
예를 들어, 사람에게 명시하기 위해 [1,2,3,...]보다 [One, Two, Three,...]로 보여주고 싶을 수도 있다.
이 때 Ndarray는 위와 같이 하려면 함수를 만들거나 Dict Data를 활용해야하지만 Series는 그럴 필요가 없다.
3. JSON 데이터로 바로 생성 가능
Dict type(JSON) 데이터를 통해 Series를 생성하면 Key값이 Index, Value값이 Data 공간에 저장되어 Series를 생성할 수 있다.
Series(data={실제 Data List}, index = {index List},
dtype = {Sereis의 Data Type}, name = {Column 이름})
Series가 여러개 모여 Table 형식으로 표현된 데이터를 말한다.
Series가 모여만들어진 하나의 Data Tablel로써 위 사진을 보면 잘 나타나있다.
# Data를 한꺼번에 담고 싶을 때
pd.DataFrame({Data}, columns={Column 이름 List})
# Data를 각각 특정 Column에 넣고 싶을 때
pd.DataFrame({"Column 이름":"Data", "Column 이름":"Data",...})
from pandas import Series, DataFrame
pd.read_csv({데이터 파일 경로 or URL}, sep={데이터 분리 문자}, header=None)
# 맨 위에서부터 N개 Data 출력
df.head(N)
# 맨 아래에서부터 N개 Data 출력
df.tail(N)
df["{Column Name}"]
df.{Column Name}
df.loc[N, {Column List}]
df[{Column List}].iloc[N]
df.iteritems()
df.sort_index() # index를 기준으로 Sorting. Default는 오름차순
df.sort_values(ascending=False)
# value를 기준으로 Sorting. ascending=False이므로 내림차순
df.data_columns = {Column List}
df.index = {Index List}
del df[{Column List}]
df.drop({Column List}, axis=1)
inplace = True
: Data 변환 결과를 DataFrame에 적용시켜 실제 DataFrame Updateinplace = False
: Data 변환을 하여 DataFrame을 반환하되, 실제 DataFrame은 변화하지 않음import pandas as pd
from tqdm import tqdm
import numpy as np
df = pd.DataFrame(np.array([1,2,3]))
# pd.Series(np.array([1,2,3])으로 설정해줘도 괜찮다
tqdm.pandas()
# 꼭 붙여줘야지만 progress_apply를 활용할 수 있다!
df.progress_apply(lambda x: x**2)
# df에 존재하는 모든 값들에 대하여 lambda Function을 적용한다
# 결과값은 [1,4,9]가 나올 것이며,
# type은 위에서 DataFrame으로 지정했으므로 결과도 DataFrame일 것이다
같은 Column과 Index를 가진 공간에 저장된 Data에 대한 연산을 수행하는, 어떻게 보면 Element-wise Operation으로 봐도 될 것이다.
여기서 중요한 점은 우리는 Pandas의 장점으로 명시적 Indexing을 할 수 있다는 점을 말했다. 반대로 말하자면 Index Number(위치)가 같더라도 Index Name이 다르다면 같은 값으로 보지 않는다는 의미이며, 반대로 Index Number가 다르더라도 Index Name이 같다면 같은 Index로 본다는 것이다.
Column Name도 같아야 같은 값으로 본다는 사실은 자명하다.
그렇다면 한쪽만 Data를 가지고 있을 경우 어떻게 연산이 수행될까?
한 쪽 값이 값이 없기 때문에 어떤 연산이 수행되든 NaN으로써 DataFrame 공간을 채운다.
즉, 결과적으로 양 쪽 Matrix가 가지고 있는 Index와 Column들은 Operation 이후 Result Matrix에 전부 존재해야 한다는 의미이다.
(Result Matrix 또한 DataFrame 형태를 가짐)
추가로, axis를 지정해 줄 경우 Broadcasting에 의한 연산이 가능해진다.
Function이나 Dict, Sequence Data 등을 활용하여 DataFrame Series를 교체하거나 DataFrame에 Series를 추가하는 것을 가능하게 해주는 기능이다.
특정 Series(Column)을 선택하고, 해당 Column 값을 활용하여 DataFrame을 확장하거나 존재하는 값을 변경하는 기능을 수행할 수 있다.
중요한 점은, "Series" 관련 메서드이므로 Series에 대해 Mapping을 수행해줘야 하며, 이 때문에 특정 Column을 선택하는 경우가 많다.
df[{추가하거나 변경할 Column Name}] = {df Series}.map(T)
Map 기능 중 데이터 변환 기능만 담당하는 특별한 함수이다.
Replace로 가능한 기능은 Map으로도 수행할 수 있지만, Map은 "추가", Replace는 "변환" 기능만을 담당하게 하여 코드 보는데 조금 더 쉽게하기 위해 만든 함수가 아닐까 싶다.
inplace Parameter 활용이 가능하며, 활용할 경우 원본 DataFrame Update를 수행하며, 반대로 활용하지 않는다면 원본 데이터 자체는 변환되지 않는다.
{df Series}.replace([Target List], [Conversion List])
{df Series}.replace({Dict type data})
Map은 Series에 포함된 Data 각각에 함수나 Dict type이 적용되었다.
하지만, 이 경우 Series 전체 합을 구하기 위해서는 값 하나씩을 추출하는 방법밖에 없을 것이다.
이런 Series 전체 값에 대한 연산을 수행하기 위해 활용되는 것이 Apply이다.
Map과는 다르게 Series 전체 원소에 대해 Function이 적용된다
특히, 내장 함수인 max, sum 등을 Function으로 활용할 수 있다는 점이 가장 큰 중요점이다
{DataFrame or Series}.apply(function)
df.describe()
df[{Column Name}].unique()
내장 함수
{Series1}.corr({Series2})
: Series1과 Series2의 상관 계수 수치 반환{Series1}.cov({Series2})
: Series1과 Series2의 공분산 수치 반환{DataFrame}.corr()
: 모든 Series 사이의 상관관계 수치 표시{DataFrame}.corrwith(Series1)
: DataFrame의 모든 Series와 Series1 사이 상관관계 수치 표현df.sort_values({Column list}, ascending=True)
Series 원소별 개수
{Series}.value_counts
pd.options.display.max_rows = x
{DataFrame}.groupby({Column List})[{연산을 수행할 Column Name}].function()
groupby를 수행할 때 Column List에 2개 이상의 data가 포함될 경우, index도 2개 이상 존재하게 된다
이런 경우 계층 구조를 가지게 되는데, 이를 Hierarchical index라고 한다.
(ex) A, B를 기준으로 Group화 시켰을 때, A 기준으로 쪼개진 Data에
다시 B 기준으로 쪼개진 Data들이 있는 구조이다
만약 A 원소 개수가 2개, B가 4개라면 총 8개로 Data가 쪼개지는 것이다
h_index.unstack()
h_index.reset_index()
h_index.stack()
h_index.sort_index(level = 0)
h_index.sort_values()
h_index.sum(level=0)
grouped.agg(sum)
grouped[{Column List}].agg([Function List])
grouped.transform({Function})
gropued.filter({filter function})
{DataFrame}.pivot_table(values = {Aggreagtion을 원하는 Column Name},
index = [{Index로 만들 Column List}],
columns= {Column으로 지정할 이름},
aggfunc = {Aggregation function},
fill_value = {Data가 없을 경우 Default로 채울 값}
)
{DataFrmae}.groupby([index + columns])[values].aggfunc.unstack()
pd.crosstab(index, columns,aggfunc).fillna({Value})
pd.merge(df_a, df_b, on={Join 기준 Column Name})
pd.merge(df_a, df_b, lef_on={df_a Column Name}, right_on = {df_b Column Name})
pd.merge(df_a,df_b, on, how ="left")
pd.merge(df_a, df_b, right_index = True, left_index = True)
pd.concat([{DataFrame 리스트}]
df_a.append(df_b)
pd.concat([{DataFrame 리스트}], axis = 1)
import sqlite3
conn = sqlite.connect("DB 주소")
data1 = pd.read_sql_query({SQL Query}, conn)
writer = pd.ExcelWriter({Excel 파일 경로}, engine="xlsxwriter")
{저장시킬 DataFrame}.to_excel(writer, sheet_name={원하는 Sheet Name})
{DataFrame}.to_pickle({저장 시키고 싶은 Pickle Name})
df = pd.read_pickle({DataFrame을 저장한 Pickle Name})