‘처음이야? 파이썬 데이터 분석’ 3주차 스터디 후기: Pandas Series & DataFrame 핵심 기능 완전 정복!

파이썬 데이터 분석’ 온라인 독학 스터디 3주차 학습 후기를 공유합니다.
지난 2주차에는 NumPy를 통해 배열 연산과 기본적인 통계 분석을 마스터했습니다. 이번 3주차에는 데이터 분석의 핵심 라이브러리인 ‘판다스(Pandas)‘에 대해 깊이 있게 학습했습니다. 특히, 판다스의 기본 데이터 구조인 ‘Series(시리즈)‘와 ‘DataFrame(데이터프레임)’의 활용법을 집중적으로 다루었습니다. 이번 학습을 통해 판다스가 데이터를 얼마나 효율적으로 다룰 수 있는지 체감할 수 있었습니다.
3.1 Pandas 개요
판다스는 파이썬에서 데이터 조작 및 분석을 위한 오픈소스 라이브러리로, 특히 정형화된 데이터 처리에 특화되어 있습니다. Series와 DataFrame이라는 강력한 데이터 구조를 제공하며, NumPy를 기반으로 합니다.
3.2 Series
Series 개념, 특징 및 리스트와의 차이점
Series는 1차원 배열과 유사한 구조로, 각 데이터에 인덱스가 부여됩니다. 단일 데이터 타입을 가지며, 파이썬 리스트와 달리 문자열 등 다양한 형태의 사용자 정의 인덱스를 가질 수 있습니다.
Series 생성 방법
리스트, 사용자 정의 인덱스를 가진 리스트, 딕셔너리 등을 사용하여 Series를 생성할 수 있습니다.
import pandas as pd
x = [10, 20, 30, 40]
y = pd.Series(x)
print(y)
y = ['a', 'b', 'c', 'd']
z = pd.Series(x, index = y)
print(z)
x = {'apple':1, 'banana':2, 'cherry': 3}
y = pd.Series(x)
print(y)
Series 구조 확인
Series의 데이터 타입(dtype
), 인덱스(index
), 값(values
) 등을 확인할 수 있습니다.
import pandas as pd
x = pd.Series([10, 20, 30, 40, 50])
print(x.dtype)
print(x.index)
print(x.values)
데이터 조회, 인덱싱 및 슬라이싱
head()
, tail()
로 데이터를 미리 보고, iloc
(위치)와 loc
(레이블)로 데이터를 선택합니다.
import pandas as pd
x = pd.Series([10, 20, 30, 40, 50, 60, 70])
print(x.head())
print(x.tail(2))
data = pd.Series([10, 20, 30, 40, 50, 60, 70])
print(data.iloc[1])
print(data.iloc[1:4])
data = pd.Series([10, 20, 30, 40], index=['a', 'b', 'c', 'd'])
print(data.loc['b'])
print(data.loc['b':'d'])
데이터 추가 및 Series 값 수정
Series에 새 요소를 추가하거나, 기존 값을 수정하고, 조건에 따라 값을 변경할 수 있습니다.
import pandas as pd
data = pd.Series([10, 20, 30], index=['a', 'b', 'c'])
data['f'] = 60
print(data)
data = pd.Series([10, 20, 30, 40], index=['a', 'b', 'c', 'd'])
data['b'] = 25
print(data)
data = pd.Series([10, 20, 30, 40], index=['a', 'b', 'c', 'd'])
data[['a', 'd']] = [15, 45]
print(data)
data = pd.Series([10, 20, 30, 40, 50], index=['a', 'b', 'c', 'd', 'e'])
data[data > 30] = data[data > 30] + 10
print(data)
인덱스 이름 변경 – rename( )
rename()
메서드를 사용하여 Series의 인덱스 이름을 변경합니다.
import pandas as pd
data = pd.Series([10,20,30], index=['a','b','c'])
data = data.rename({'a':'x', 'b':'y'})
print(data)
데이터 통계 및 요약
평균, 합계, 분산, 표준편차 등 Series의 값들에 대한 통계량을 계산합니다.
import pandas as pd
data = pd.Series([10, 20, 30, 40, 50])
average = data.mean()
print(average)
total = data.sum()
print(total)
data = pd.Series([10, 20, 30, 40, 50])
variance = data.var()
std_dev = data.std()
print("분산:", variance)
print("표준편차:", std_dev)
고윳값 확인
value_counts()
로 Series 내 각 고유한 값들의 빈도를 확인합니다.
import pandas as pd
data = pd.Series(['a','b','a','c','b','a'])
value_counts = data.value_counts()
print(value_counts)
value_counts_normalized = data.value_counts(normalize=True)
print(value_counts_normalized)
데이터 필터링 및 조건 선택
단일 또는 다중 조건으로 Series 데이터를 필터링합니다.
import pandas as pd
data = pd.Series([10,20,30,40,50], index=['a','b','c','d','e'])
filtered_data = data[data > 25]
print(filtered_data)
and_filter = data[(data > 25) & (data < 35)]
print("AND 조건 필터링 결과:")
print(and_filter)
or_filter = data[(data < 25) | (data > 35)]
print("\nOR 조건 필터링 결과:")
print(or_filter)
Series의 데이터 연결 – concat( )
pd.concat()
함수를 사용하여 여러 Series를 연결합니다.
import pandas as pd
series1 = pd.Series([1,2,3], index=['a','b','c'])
series2 = pd.Series([4,5], index=['d','e'])
append_series = pd.concat([series1, series2])
print("연결된 Series:")
print(append_series)
데이터 정렬
sort_values()
로 값을 기준으로, sort_index()
로 인덱스를 기준으로 Series를 정렬합니다.
import pandas as pd
series1 = pd.Series([1,2,3,4], index=['a','b','c','d'])
x = pd.Series([10,20,30,40,50]).sort_values()
print("오름차순 정렬 결과:")
print(x)
y = pd.Series([10,20,30,40,50]).sort_values(ascending=False)
print("\n내림차순 정렬 결과:")
print(y)
data = pd.Series([20, 10, 40, 30], index=['a','b','c','d'])
x = data.sort_index()
print("인덱스 기준 오름차순 정렬 결과:")
print(x)
y = data.sort_index(ascending=False)
print("\n인덱스 기준 내림차순 정렬 결과:")
print(y)
데이터 그룹화 및 집계
groupby()
메서드를 사용하여 Series 데이터를 그룹화하고, 합계, 평균 등 집계 함수를 적용합니다.
import pandas as pd
data = pd.Series([10,20,30,10,20,30], index=['a','b','a','b','a','b'])
x = data.groupby(level=0).sum()
print("그룹화 후 합계:")
print(x)
y = data.groupby(level=0).mean()
print("\n그룹화 후 평균:")
print(y)
grouped_agg = data.groupby(level=0).agg(['sum', 'mean', 'count'])
print("그룹화 후 여러 집계 함수 결과:")
print(grouped_agg)
3.3 DataFrame
DataFrame 개념 및 리스트와의 차이점
DataFrame은 행과 열로 구성된 2차원 테이블 형태의 데이터 구조입니다. 각 열은 Series 객체로 구성되며, 파이썬 리스트와 달리 열 이름과 풍부한 분석 기능을 제공합니다.
DataFrame 생성 방법
리스트의 리스트, 딕셔너리, NumPy 배열 등으로 DataFrame을 생성합니다.
import pandas as pd
import numpy as np
x = [
['Ant',25,'Seoul'],
['Bee',30,'Busan']
]
df = pd.DataFrame(x, columns=['Name', 'Age', 'City'])
print(df)
x = {
'Name': ['Ant','Bee','Cat'],
'Age': [25,30,35]
}
df = pd.DataFrame(x)
print(df)
x = np.array([
['Ant',25,'Seoul'],
['Bee',30,'Busan']
])
df = pd.DataFrame(x, columns=['Name', 'Age', 'City'])
print(df)
DataFrame 구조 확인
shape
, columns
, index
, info()
를 통해 DataFrame의 구조를 확인합니다.
import pandas as pd
data = pd.DataFrame({
'Name': ['Ant', 'Bee', 'Cat'],
'Age': [24, 27, 22]
})
print(data.shape)
print(data.columns)
print(data.index)
data.info()
데이터 조회
head()
와 tail()
로 DataFrame의 상위/하위 데이터를 확인합니다.
import pandas as pd
x = pd.DataFrame({
'Name': ['Ant', 'Bee', 'Cat', 'Dog', 'Eagle'],
'Age': [24, 27, 22, 32, 28]
})
print(x.head())
print(x.tail(3))
인덱싱 및 슬라이싱
iloc
(위치)와 loc
(레이블)로 DataFrame의 특정 행과 열을 선택합니다.
import pandas as pd
data = pd.DataFrame({
'Name': ['Ant', 'Bee', 'Cat'],
'Age': [24, 27, 22],
'City': ['Seoul', 'Busan', 'Incheon']
})
print(data.iloc[1,2])
print(data.iloc[1:3, 0:2])
data = pd.DataFrame({
'Name': ['Ant', 'Bee', 'Cat'],
'Age': [24, 27, 22],
'City': ['Seoul', 'Busan', 'Incheon']
}, index=['A','B','C'])
print(data.loc['A', 'City'])
print(data.loc['A':'B', 'Name':'Age'])
데이터 추가
DataFrame에 새로운 열을 추가합니다.
import pandas as pd
data = pd.DataFrame({
'Name': ['Ant', 'Bee', 'Cat'],
'Age': [24, 27, 22]
})
data = data.assign(City=['Seoul', 'Busan', 'Incheon'])
print(data)
data['Score'] = [85, 90, 95]
print(data)
DataFrame 값 수정
열 전체, 특정 위치, 또는 조건에 따라 DataFrame의 값을 수정합니다.
import pandas as pd
data = pd.DataFrame({
'Name': ['Ant', 'Bee', 'Cat'],
'Score': [85, 90, 95]
})
data.loc[1, 'Score'] = 88
print(data)
data.loc[0, 1] = 80
print(data)
data.loc[[0, 2], 'Score'] = [75, 85]
print(data)
data = pd.DataFrame({
'Name': ['Ant', 'Bee', 'Cat'],
'Score': [85, 90, 95],
'Passed': ['True', 'True', 'False']
})
data.loc[data['Score'] >= 90, 'Passed'] = True
print(data)
data.loc[(data['Score'] >= 90) & (data['Name'] == 'Bee'), 'Score'] = 100
print(data)
열 이름 변경
rename()
메서드로 DataFrame의 열 이름을 변경합니다.
import pandas as pd
data = pd.DataFrame({
'Name': ['Ant', 'Bee', 'Cat'],
'Score': [85, 90, 95],
'City': ['Seoul', 'Busan', 'Incheon']
})
data = data.rename(columns={'Name':'Full Name', 'City': 'Location'})
print(data)
데이터 통계 및 요약
describe()
로 숫자형 열의 요약 통계를 보고, 특정 열의 통계량도 계산합니다.
import pandas as pd
data = pd.DataFrame({
'Math': [85, 90, 95, 100, 80],
'Science': [88, 92, 85, 89, 94]
})
print(data.describe())
math_mean = data['Math'].mean()
science_sum = data['Science'].sum()
print("Math 평균:", math_mean)
print("Science 합계:", science_sum)
고윳값 확인
value_counts()
로 각 열의 고윳값 빈도를 분석합니다.
import pandas as pd
data = pd.DataFrame({
'Fruit': ['apple', 'banana', 'apple', 'orange', 'banana', 'apple'],
'Color': ['red', 'yellow', 'red', 'orange', 'yellow', 'red']
})
fruit_counts = data['Fruit'].value_counts()
print(fruit_counts)
for column in data.columns:
print(f"'{column}' 열의 고윳값 빈도:")
print(data[column].value_counts(), "\n")
데이터 필터링 및 조건 선택 – 다중 조건 필터링
여러 조건을 동시에 적용하여 DataFrame 데이터를 필터링합니다.
import pandas as pd
data = pd.DataFrame({
'Name': ['Ant', 'Bee', 'Cat', 'Dog'],
'Age': [24, 27, 22, 32],
'Score': [88, 95, 85, 90]
})
and_filtered_data = data[(data['Age'] > 20) & (data['Score'] > 80)]
print("Age가 20보다 크고 Score가 80보다 큰 값:")
print(and_filtered_data)
or_filtered_data = data[(data['Age'] > 20) | (data['Score'] > 80)]
print("\nAge가 20보다 크거나 Score가 80보다 큰 값:")
print(or_filtered_data)
데이터 병합 및 결합
pd.merge()
로 특정 키를 기준으로 DataFrame을 병합하고, pd.concat()
으로 단순히 이어 붙입니다.
import pandas as pd
df1 = pd.DataFrame({
'ID': [1, 2, 3],
'Name': ['Ant', 'Bee', 'Cat']
})
df2 = pd.DataFrame({
'ID': [2, 3, 4],
'Score': [88, 92, 85]
})
merged_df = pd.merge(df1, df2, on='ID', how='inner')
print(merged_df)
merged_df_left = pd.merge(df1, df2, on='ID', how='left')
print(merged_df_left)
df1 = pd.DataFrame({
'ID': [1, 2, 3],
'Score': [90, 80, 85]
})
df2 = pd.DataFrame({
'ID': [4, 5, 6],
'Score': [75, 95, 88]
})
concat_df = pd.concat([df1, df2], axis=0)
print(concat_df)
concat_df_col = pd.concat([df1, df2], axis=1)
print(concat_df_col)
데이터 정렬
sort_values()
로 값을 기준으로, sort_index()
로 인덱스를 기준으로 DataFrame을 정렬합니다.
import pandas as pd
data = pd.DataFrame({
'Name': ['Ant', 'Bee', 'Cat', 'Dog'],
'Age': [24, 27, 22, 32],
'Score': [88, 95, 85, 90]
})
sorted_df = data.sort_values(by='Age')
print('Age 기준 오름차순 정렬 결과:')
print(sorted_df)
sorted_df_desc = data.sort_values(by='Score', ascending=False)
print("\nScore 기준 내림차순 정렬 결과:")
print(sorted_df_desc)
data = pd.DataFrame({
'Name': ['Ant', 'Bee', 'Cat', 'Dog'],
'Age': [27, 27, 22, 32],
'Score': [88, 95, 85, 90]
})
sorted_df_multi = data.sort_values(by=['Age', 'Score'], ascending=[True, False])
print('Age 오름차순, Score 내림차순 정렬 결과:')
print(sorted_df_multi)
data = pd.DataFrame({
'Name': ['Ant', 'Bee', 'Cat', 'Dog'],
'Age': [24, 27, 22, 32],
'Score': [88, 95, 85, 90]
})
sorted_index_df = data.sort_index()
print("행 인덱스 기준 오름차순 정렬 결과:")
print(sorted_index_df)
sorted_columns_df = data.sort_index(axis=1, ascending=False)
print("\n열 인덱스 기준 내림차순 정렬 결과:")
print(sorted_columns_df)
데이터 그룹화 및 집계
groupby()
메서드를 사용하여 DataFrame 데이터를 그룹화하고, 각 그룹에 대해 합계, 평균 등 집계 함수를 적용합니다.
import pandas as pd
data = pd.DataFrame({
'Category': ['A', 'B', 'A', 'B', 'A', 'B'],
'Values': [10, 20, 30, 40, 50, 60]
})
grouped_sum = data.groupby('Category')['Values'].sum()
print("그룹화 후 합계:")
print(grouped_sum)
data = pd.DataFrame({
'Category': ['A', 'A', 'B', 'B', 'A', 'B'],
'Type' : ['X', 'Y', 'X', 'Y', 'X', 'Y'],
'Values': [10, 20, 30, 40, 50, 60]
})
grouped_mean = data.groupby(['Category', 'Type'])['Values'].mean()
print("그룹화 후 평균:")
print(grouped_mean)
grouped_agg = data.groupby('Category')['Values'].agg(['sum', 'mean', 'count'])
print("그룹화 후 여러 집계 함수 결과:")
print(grouped_agg)
3.4 Series와 DataFrame
Series와 DataFrame의 차이점
DataFrame은 여러 개의 Series가 열 방향으로 나란히 놓인 형태입니다. Series는 1차원, DataFrame은 2차원 데이터 구조이며, DataFrame의 각 열은 그 자체가 Series 객체입니다. 이러한 관계 덕분에 Series의 기능들이 DataFrame의 개별 열에도 적용됩니다.
3주차 마무리
이번 3주차 스터디를 통해 판다스의 Series와 DataFrame에 대한 이해를 높일 수 있었습니다. 1차원 Series의 기본 개념부터 2차원 DataFrame의 다양한 데이터 조작 및 분석 기법까지, 판다스의 강력한 기능들을 직접 실습하며 익혔습니다. 특히 DataFrame은 실제 데이터 분석에서 매우 유용하게 활용될 것이라는 점을 깨달았습니다.