오늘부터 일주일은 처음 파이썬 기초를 가르쳐주셨던 강사님이 다시 오셨습니다.
반가웠습니다. 짧은 시간도 인연인지 강의도 익숙하고, 잘 들을 수 있었습니다.
내용은 쉽지 않았습니다. pandas를 향후에 어느정도 쓸지 모르겠지만 교안 내용을 봤을때
하루에 정리하기는 좀 터무니 없는 양이다 라는 생각을 했습니다.
그래도 강의를 듣다보니 이런 부분은 함수를 하나씩 설명하기 보다는 찾아가면서
문제해결 하는게 맞다는 생각이 들었습니다. 양이 많기도 하고, 다양한 예제를
모두 정리할 수는 없는 일이니까요.
주요한 함수와 주의사항을 알려주고, 직접 사용해보도록 하는게 맞다는 생각을 했습니다.
우리 모두 클래스 배웠으니까요..;;
pandas 개요
import pandas as pd
test = pd.read_csv("/content/sample_data/california_housing_test.csv")
print(test.head())
print('')
print(test.tail())
print('')
# DataFrame 의 요약 정보 출력
print(test.info())
print(test.describe())
간단하게 샘플 csv 파일 불러오고, test 객체에할당합니다.head()
함수는 파일의 상단에 5개 행을 출력합니다.tail()
함수는 파일의 말단에 5개 행을 출력합니다.
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3000 entries, 0 to 2999
Data columns (total 9 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 longitude 3000 non-null float64
1 latitude 3000 non-null float64
2 housing_median_age 3000 non-null float64
3 total_rooms 3000 non-null float64
4 total_bedrooms 3000 non-null float64
5 population 3000 non-null float64
6 households 3000 non-null float64
7 median_income 3000 non-null float64
8 median_house_value 3000 non-null float64
dtypes: float64(9)
memory usage: 211.1 KB
None
위의 정보는 info()
함수의 출력 결과입니다.info()
함수는 이 객체(csv 파일)의 대략적인 정보를 출력합니다.
클래스 정보, 데이터 양과 컬럼수와 컬럼의 이름, Non-Null의 수, 각 컬럼의 데이터타입 등
정보를 출력합니다.
Null 이 있으면 머신러닝 모델의 대부분을 돌리지 못합니다. (딥러닝도 거의 동일)
xgboost / 딥러닝 일부 모델 중 옵션변경 할 수 있습니다. (Null -> 하나의 값! 으로 치환해서 쓰는 경우 있음)
Null -> 0(X), NAN(X) Null을 임의로 치환하는 것은 굉장히 위험합니다.
Null 최대한 제거하고 분석하는 것을 추천 -> Null을 가지고 있는 데이터가 다른 데이터와 다른지 파악하는 것이 중요합니다.
이런 것보다 더 중요하다고 말씀하신건 요구정의서 / 컬럼에 대한 히스토리! 를 파악하는 것입니다.
데이터 다루는 건 클래스와 함수 하나하나 그 자체가 중요하다기 보다는 결국 인사이트를 가지고, 판단하는 것이
중요하다는 것이겠지요. 결국 데이터를 다루는 건 어떻게든 할 수 있으니까요.
longitude latitude housing_median_age total_rooms \
count 3000.000000 3000.00000 3000.000000 3000.000000
mean -119.589200 35.63539 28.845333 2599.578667
std 1.994936 2.12967 12.555396 2155.593332
min -124.180000 32.56000 1.000000 6.000000
25% -121.810000 33.93000 18.000000 1401.000000
50% -118.485000 34.27000 29.000000 2106.000000
75% -118.020000 37.69000 37.000000 3129.000000
max -114.490000 41.92000 52.000000 30450.000000
total_bedrooms population households median_income \
count 3000.000000 3000.000000 3000.00000 3000.000000
mean 529.950667 1402.798667 489.91200 3.807272
std 415.654368 1030.543012 365.42271 1.854512
min 2.000000 5.000000 2.00000 0.499900
25% 291.000000 780.000000 273.00000 2.544000
50% 437.000000 1155.000000 409.50000 3.487150
75% 636.000000 1742.750000 597.25000 4.656475
max 5419.000000 11935.000000 4930.00000 15.000100
median_house_value
count 3000.00000
mean 205846.27500
std 113119.68747
min 22500.00000
25% 121200.00000
50% 177650.00000
75% 263975.00000
max 500001.00000
print(test.describe())
의 출력 결과입니다.
DataFrame의 통계적 요약 정보를 출력합니다.
Min / Max -> 9999999 / -9999999 / 이상한 문자로 된 값 ********
이런 값들이 Min 이나 Max에 나오니 걸러낼 수 있습니다.
Mean -> 평균이 우리가 아는 수치와 비슷한지 확인할 수 있습니다.
25% 50% 75% -> 데이터가 편중되어 있는지 아니면 잘 분포되어 있는지 확인할 수 있습니다. -> 표준편차
# inplace 매개변수를 사용하지 않는 경우
# 판다스 대부분의 메서드에서는 기본적으로 데이터프레임의 복사본을 수정하고, 원본 데이터프레임은 그대로 유지
test = df.dropna()
# inplace=True를 사용하는 경우
# 이 매개변수를 True로 설정하면, 메서드는 데이터프레임의 복사본을 만들지 않고 원본 데이터프레임을 직접 수정
test.dropna(inplace=True)
위의 함수는 결측치가 나왔을때 데이터프레임의 원본을 유지하는지 직접 수정할 것인지를 설정할 수 있습니다.
import pandas as pd
import numpy as np
# 샘플 데이터프레임 생성
# 문자형 데이터는 describe() 사용해도 통계량이 나오지 않는다. -> count() 정도로 수만 셀 수 있다.
data = {'이름': ['홍길동', '임꺽정', None],
'나이': [30, None, 40],
'도시': ['서울', '부산', '광주']}
df = pd.DataFrame(data)
# 결측치가 포함된 데이터프레임 출력
print("원본 데이터프레임:\n", df)
# 결측치 제거
df.dropna(inplace=True) # inplace 잘못써서 원본 자체를 날릴수도 있다. 주의!!
# 결측치가 제거된 데이터프레임 출력
print("\n결측치 제거 후 데이터프레임:\n", df)
inplace 잘못써서 원본 자체를 날릴수도 있습니다. 주의가 필요합니다.
데이터프레임과 시리즈
# Pandas DataFrame 예시
import pandas as pd
df = pd.DataFrame({
'Name': ['Alice', 'Bob', 'Charlie'],
'Age': [25, 30, 35],
'City': ['New York', 'Paris', 'Berlin']
})
# 각 속성 호출
print("Shape:", df.shape)
print("Data Types:\n", df.dtypes)
print("Index:", df.index)
print("Columns:", df.columns)
출력결과
Shape: (3, 3)
Data Types:
Name object
Age int64
City object
dtype: object
Index: RangeIndex(start=0, stop=3, step=1)
Columns: Index(['Name', 'Age', 'City'], dtype='object')
데이터프레임 df의 각 속성을 출력해서 볼 수 있습니다.
import pandas as pd
# 예시 데이터프레임 생성
data = {
'Name': ['Alice', 'Bob'], # 문자열 타입
'Age': ['25', '30'], # 숫자 데이터를 문자열로 표현
'Member': ['True', 'False'], # 불린 데이터를 문자열로 표현
'Join Date': ['2021-01-01', '2021-07-01'] # 날짜 데이터를 문자열로 표현
}
df = pd.DataFrame(data)
# 결과 출력
print(df)
print(df.dtypes)
DB -> 문자열! -> 메모리 / 저장용량 효율적! 이라고 합니다. 강사님께서 확실하진 않다고 하셨지만^^
숫자나 날짜도 보통 데이터타입 보다 문자열로 되어 있는 경우가 많습니다.
# 데이터 타입 변환
df['Age'] = df['Age'].astype(int) # 'Age' 열을 정수형으로 변환
df['Member'] = df['Member'].astype(bool) # 'Member' 열을 불린형으로 변환
df['Join Date'] = pd.to_datetime(df['Join Date']) # 'Join Date' 열을 datetime으로 변환
# 결과 출력
print(df)
print(df.dtypes)
결과 출력
Name Age Member Join Date
0 Alice 25 True 2021-01-01
1 Bob 30 True 2021-07-01
Name object
Age int64
Member bool
Join Date datetime64[ns]
dtype: object
이렇게 열을 형변환 할 수 있습니다.
import pandas as pd
import numpy as np
# 예시 데이터프레임 생성
data = {
'Name': ['Alice', 'Bob', 'Charlie'],
'Age': [25, 30, 35],
'City': ['New York', 'Paris', 'Berlin']
}
df = pd.DataFrame(data)
# 단일 열 선택 -> 결과는 Series
age_series = df['Age']
print(type(age_series))
출력결과
<class 'pandas.core.series.Series'>
# 다중 열 선택 -> 결과는 DataFrame
subset_df = df[['Name', 'City']]
print(type(subset_df))
출력결과
<class 'pandas.core.frame.DataFrame'>
컬럼이 한개 있을때는 Series 클래스 이고, 컬럼이 두개 이상 있을때는 DataFrame 클래스입니다.
출력해보면 확실하게 알 수 있습니다.
# loc 사용 예시 - 변수명을 넣는다.
print(df.loc[:, 'Age'])
# iloc 사용 예시 - 위치를 넣는다.
print(df.iloc[:, 1])
loc[]
는 변수명을 넣어서 해당 컬럼을 출력할 수 있고, iloc[]
는 위치(숫자)를 넣어서 출력할 수 있습니다.
아무래도 loc[]
이 명시적이고 쓰기 좋을듯 합니다. iloc[]
는 잘못 알고 있다면 원하지 않는 출력이 발생할 수 있습니다.
# 결측치 확인 isnull -> null 이 아니면 False, null 이면 True
print(df['Age'].isnull())
컬럼에 결측치가 있는지 확인하고, 결측치가 있을때 True를 반환합니다.
이 결과를 가지고 결측치를 포함할지 안할지 결정할 수 있겠지요?
# series 메서드 활용
import pandas as pd
# Series 생성
data = pd.Series([10, 20, 20, 30, 40, 30, 30, 15])
# sum(), mean(), value_counts() 사용 예시
print("Sum:", data.sum()) # 합계 series 에서만 작동
print("Mean:", data.mean()) # 평균 series 에서만 작동
print("Value Counts:\n", data.value_counts()) # 빈도 계산 series 에서만 작동
데이터 타입이 series 일 경우 사용 가능한 함수들입니다.
합계, 평균, 빈도계산 등은 컬럼이 하나여야 가능한 것들입니다.
# Series 와 DataFrame 을 다루는 메서드가 다름
import pandas as pd
# Series 생성
data = pd.Series([10, 15, 20, 25, 30, 20, 15])
# 다양한 메서드 활용
print("Minimum:", data.min()) # 최소값
print("Maximum:", data.max()) # 최대값
print("Standard Deviation:", data.std()) # 표준편차
print("Variance:", data.var()) # 분산 분산 에 root 씌운게 표준편차
print("Number of Unique Values:", data.nunique()) # 고유값 개수
# 데이터프레임 요약
df = pd.DataFrame({
'Age': [25, 30, 35, 40, 45],
'Salary': [50000, 55000, 60000, 65000, 70000]
})
print("\nDataFrame Summary:\n", df.describe())
print("\nDataFrame Info:")
df.info()
Series 와 DataFrame 은 다루는 메서드가 다릅니다.
Series 는 여러 메소드 통해서 하나하나 출력할 수 있고, DataFrame 은 info()
통해서 정보를 출력할 수 있습니다.
# CSV 파일 로드
file_path = '/content/sample_data/california_housing_test.csv'
test = pd.read_csv(file_path)
test_series = test['housing_median_age']
print(test_series)
# 각 요소에 1 더하기
stars_plus_one = test_series + 1
print("Stars Plus One:\n", stars_plus_one.head())
이렇게 컬럼의 각 요소의 값에 1을 일괄적으로 더할 수도 있습니다.
# 각 요소에 2 곱하기
stars_times_two = test_series * 2
print("Stars Times Two:\n", stars_times_two.head())
이렇게 2를 곱할 수도 있습니다.
# 30 보다 큰 나이 찾기
# 불린 연산이 가능하다 -> 해당하는 값만 가져올 수 있다.
high_age = test_series > 30.0
print("High age:\n", high_age.head())
High age:
0 False
1 True
2 False
3 False
4 False
Name: housing_median_age, dtype: bool
결과가 불린 값으로 나와서 해당하는 값만 가져올 수도 있습니다.
import pandas as pd
df = pd.DataFrame({
'A': [1, 2, 3],
'B': [4, 5, 6],
'C': [7, 8, 9]
})
print(df)
print()
# 열 이름 변경
# columns({변경하기전 : 변경한후 , 변경하기전 : 변경한 후})
df = df.rename(columns={'A': 'X', 'B': 'Y', 'C': 'Z'})
print(df)
출력 결과
A B C
0 1 4 7
1 2 5 8
2 3 6 9
X Y Z
0 1 4 7
1 2 5 8
2 3 6 9
이렇게 열 이름을 변경할 수도 있습니다.
import pandas as pd
df = pd.DataFrame({
'Name': ['Alice', 'Bob', 'Charlie'],
'Age': [25, 30, 35]
})
# 'Salary'라는 새 열 추가
df['Salary'] = [50000, 60000, 70000] # 다른 데이터 프레임을 가져오고 사용하는 경우 있음.
print(df)
이건 많이 사용하지 않는 다고 합니다. concat / join -> 데이터 결합을 많이 한다고 합니다.
기업데이터의 경우는 기존 데이터를 다루는 경우가 많고, 새로 생성하는 경우는 많지 않다고 합니다.
# 'Age' 열 삭제
df = df.drop(['Age', 'Name'], axis=1) # axis = 1 열/컬럼 의미 꼭 넣어줘야함(주의)
print(df)
drop 은 중요합니다.
첫번째로 ram 효율을 증대하기 위해서 import 할때만 전체를 가져오되 -> 작업을 할때는 필요한 변수만 가져와서 작업할 수 있습니다.
두번째로 머신러닝 / 딥러닝 ! -> 분석에 필요한 변수만 가져올때 사용할 수 있습니다.
import pandas as pd
# Sample DataFrames
df1 = pd.DataFrame({'A': [1, 2], 'B': [3, 4]})
df2 = pd.DataFrame({'A': [5, 6], 'B': [7, 8]})
# 가로로 연결 (열 방향)
result = pd.concat([df1, df2], axis=1)
print(df1)
print()
print(df2)
print()
print(result)
A B
0 1 3
1 2 4
A B
0 5 7
1 6 8
A B A B
0 1 3 5 7
1 2 4 6 8
데이터 가로로 연결할 수 있는 방법입니다.
import pandas as pd
# Sample DataFrames with different column names
df1 = pd.DataFrame({'A': [1, 2], 'B': [3, 4]})
df2 = pd.DataFrame({'X': [5, 6], 'Y': [7, 8]})
print(df1)
print()
print(df2)
print()
# 가로로 연결 (열 방향) - ignore_index=True 열 이름 다름
# 주의할 점 - df1과 df2가 동일한 행을 가지고 있을때!
# 동일하지 않을땐 join 이용
result = pd.concat([df1, df2], axis=1, ignore_index=True)
print(result)
가로로 연결 할때 동일한 행을 가지고 있을때 사용할 수 있습니다.
동일하지 않다면 join 등을 이용해야 합니다.
import pandas as pd
# Sample DataFrames
df1 = pd.DataFrame({'A': [1, 2], 'B': [3, 4]})
df2 = pd.DataFrame({'A': [5, 6], 'B': [7, 8]})
print(df1)
print()
print(df2)
print()
# 세로로 연결 (행 방향)
result = pd.concat([df1, df2]) # 세로 연결할땐 axis=0 이고, 생략된 상태
print(result)
A B
0 1 3
1 2 4
A B
0 5 7
1 6 8
A B
0 1 3
1 2 4
0 5 7
1 6 8
데이터 세로로 연결할 수 있는 방법입니다. 아무래도 이걸 더 많이 사용하겠지요?
import pandas as pd
# Sample DataFrames with different index
df1 = pd.DataFrame({'A': [1, 2], 'B': [3, 4]}, index=[0, 1])
df2 = pd.DataFrame({'A': [5, 6], 'B': [7, 8]}, index=[2, 3])
print(df1)
print()
print(df2)
print()
# 세로로 연결 (행 방향) - 인덱스 다름
result = pd.concat([df1, df2], ignore_index=True)
print(result)
언제 사용할까요? 2023년 1월 ~ 2024년 1월 -> 분석 열심히 하고 있는데 2024년 2월 데이터가 신규로 오는 경우에
사용할 수 있습니다. 데이터컬럼이 동일할때 세로 결합이 유용합니다.
# 1. 조건에 대해서 / 내가 무엇을 할지에 대해서 잘 정의
# MAU -> 월별 활성화 고객수
# * 우리 웹에 1회 방문
# * 우리 윕에서 실제로 1회 구매한(유효고객)
# * 3회 이상
# 방문횟수 로그기록 웹사이트활동
# 고객A 1
# 고객B 2
# 고객C 3
# pandas로 구현하는건 어렵지 않을 수 있다.
# 2. 이 중에서 반복작업!
# -> 대시보드
# -> 반복문 / 함수! -> 프로그램화!
# 3. 반복이 되면 패턴!
# -> 패턴을 가지고 EDA 추가적으로 수행
# -> 해당 패턴이 왜 발생되었는가?
다시 한번 반복해서 말씀해주신 것 정리해보면 결국 기준을 어떻게 정의하고, 데이터를 사용하는지가 중요하다는 것입니다.
pandas로 구현하는 건 어렵지 않을 수 있고, 예쁘게 꾸밀 수 있지만 데이터가 정의가 잘 되어 있지 않거나 진짜 데이터가 아니라면
아무 의미가 없습니다.
이 이후에는 EDA 실습을 진행했습니다. 여러가지 배웠지만 코드는 짧아도 출력 결과를 여기에 다 쓰기는 좀 어려워서
과감하게 제외합니다.nunique()
로 고유값 확인 할 수 있었고, 문자형을 숫자로 변경하는 방법 1. astype, 2. to_numeric
을 배웠습니다.
그외 중복 제거, 이상치 제거 등을 이용해 박스플롯에 뿌려보는 것까지 해봤습니다.^^
이것들을 활용하면 멋진 admin페이지도 만들 수 있을 것 같습니다.
유의미한 데이터가 쌓이는게 더 중요하겟지만요.
이상입니다. 내일도 화이팅!!
'오름캠프(23.12.28 ~ 24.4.18)' 카테고리의 다른 글
오름캠프 학습일지(2024/01/24) - 5주차 3일 (5) | 2024.01.24 |
---|---|
오름캠프 학습일지(2024/01/23) - 5주차 2일 (1) | 2024.01.23 |
오름캠프 학습일지(2024/01/19) - 4주차 5일 (0) | 2024.01.19 |
오름캠프 학습일지(2024/01/18) - 4주차 4일 (0) | 2024.01.18 |
오름캠프 학습일지(2024/01/17) - 4주차 3일 (0) | 2024.01.17 |