빅데이터 QAQC_3기/빅데이터 QAQC_3기 TIL

TIL_250929

usungusung 2025. 9. 29. 21:07

Today I learned

 

1. QAQC 문제풀이 가이드

1-1. 컬럼별 결측치 찾기

import numpy as np
import pandas as pd

df = pd.DataFrame({
'A': [1, None, 3, None, 5],
'B': [10, 20, 30, 40, 50],
'C': [np.nan, np.nan, 2.5, 3.1, None]
})

a = df.isnull().sum()
print(a)
 
A 2 B 0 C 3 dtype: int64

 

1-2. 특정 컬럼 제거 후 행 갯수 출력

import numpy as np
import pandas as pd

titanic = pd.DataFrame({
'Name': ['A', 'B', 'C', 'D', 'E'],
'Age': [25, None, 31, None, 40],
'Fare': [10.5, 20.0, 30.5, 40.0, 50.5]
})

titanic_dropped = titanic.dropna() 
print(len(titanic_dropped))
 
3

# Age 칼럼에 None이 제거되므로, titanic_dropped의 길이는 3임

 

1-3. 특정 컬럼의 결측치 비율을 계산하기

import numpy as np
import pandas as pd

df = pd.DataFrame({
'Age': [22, None, 35, None],
'Cabin': [None, 'C85', None, None],
'Embarked': ['S', None, 'C', None]
})

missing_ratio = ((df['Age'].isnull().sum() / len(df['Age']))*100).round(1)
print(missing_ratio)
 
50.0

# 전체 Age 컬럼의 길이로 결측치의 합을 나눠 100으로 곱하고 소숫점 1의 자리까지 나타냄

 

2-1. 배송 소요 일수 구하기

import pandas as pd

orders_df = pd.DataFrame({
'order_id': ['ORD001', 'ORD002', 'ORD003'],
'order_date': ['2024-01-01', '2024-02-10', '2024-03-05'],
'delivery_date': ['2024-01-04', '2024-02-15', '2024-03-07']
})

orders_df['order_date'] = pd.to_datetime(orders_df['order_date'])
orders_df['delivery_date'] = pd.to_datetime(orders_df['delivery_date'])

orders_df['delivery_days'] = (orders_df['delivery_date'] - orders_df['order_date']).dt.days

print(orders_df['delivery_days'])
 
0 3
1 5
2 2
Name: delivery_days, dtype: int64

# 정답의 0,1,2는 행의 위치고, 3, 5, 2가 delivery date에서 order_date를 뺀 값이다. 

# .dt.days : dt는 datetime 관련 속성으로 접근할 수 있게 해주며, days는 기간을 '일' 단위의 정수로 바꿔준다. 즉 며칠 차이인지 정수로 변환해서 넣어주는 코드임.

 

2-2. 결측치를 평균값으로 대체하기

import pandas as pd


df = pd.DataFrame({
'Name': ['A', 'B', 'C', 'D'],
'Age': [20, None, 30, None]
})

a = df['Age'].mean()


df['Age'] = df['Age'].fillna(a)

print(df['Age'])
 
0 20.0
1 25.0
2 30.0
3 25.0
Name: Age, dtype: float64

# 0, 1, 2, 3은 행의 위치, 우측의 20, 25, 30, 25는 Age 칼럼에서 None 값을 평균으로 대체한 값이다.

# 변수 a에 Age 칼럼의 평균을 넣어주었고, fillna를 통해 None 값을 평균으로 바꿔주었다.

 

2-3. 빠른 배송(3일 이내) 주문 갯수를 계산하기

import pandas as pd

orders_df = pd.DataFrame({
    'order_id': ['ORD001', 'ORD002', 'ORD003', 'ORD004', 'ORD005', 'ORD006'],
    'order_date': ['2024-01-15', '2024-02-20', '2024-03-10', '2024-04-01', '2024-05-05', '2024-06-01'],
    'delivery_date': ['2024-01-18', '2024-02-25', '2024-03-15', '2024-04-05', '2024-05-10', '2024-06-06']
})

orders_df['order_date'] = pd.to_datetime(orders_df['order_date'])
orders_df['delivery_date'] = pd.to_datetime(orders_df['delivery_date'])

orders_df['delivery_days'] = (orders_df['delivery_date'] - orders_df['order_date']).dt.days

count_3 = (orders_df['delivery_days'] <= 3)
 

print(count_3.sum())
 
1

# order_date 칼럼과 delivery_date 칼럼을 datetime의 형태로 바궈주고, 새  delivery_days 칼럼을 만들어 delivery_date에서 order_date를 뺀 값을 넣어준다. 날짜를 계산하기 위해 .dt.days를 붙였다.

# 새 변수 count_3는 delivery_days 칼럼의 값이 3 이하인 경우만 True가 나오는 불리언 시리즈이며, 합계를 구하면 True를 1로, False를 0으로 간주하여 결과가 나온다.

 

 

2. (라이브세션) Python 라이브러리 세션 3회차

1) CSV 파일 다루기

What CSV? -> Comma Seperated Value, 쉼표로 구분한 데이터 형식

 

ex1) 기본적인 csv 파일 읽기

import csv

#기본적인 csv 파일 읽기
with open('csv_test.csv', 'r', encoding = 'utf-8') as file: #r: 리딩한다는 뜻, 인코딩 없은면 깨짐
    csv_reader = csv.reader(file)
    for row in csv_reader:
        print(row)

#with 문으로 가지고 와서 pandas 상에서 첫 번째 줄을 header
# pandas 자체 모듈에서 csv : read_csv()
with open("csv_test.csv", 'r', encoding = 'utf-8') as file:
    csv_reader = csv.DictReader(file)


    for row in csv_reader:
        print(row["\ufeff이름"], row["나이"], row["직업"])

 

ex2) 리스트 형태의 데이터 쓰기

data = [
    ['이름', '나이', '직업'],
    ['유서윤', '34', '서점MD'],
    ['남지후', '27', '출판편집자']
]

data

 

2) JSON 파일 다루기

ex) 읽기, 쓰기, 저장하기

import json

# JSON 파일 읽기
with open('json_test.json', 'r', encoding='utf-8') as file: # with문을 통해 읽어올거임
    data = json.load(file) # 파일의 JSON을 파이썬 객체로 변환
    print(data)
    print(data['이름'])# 딕셔너리처럼 접근, R꼭 with 문으로만 열 수 있는건 아니다!
       
        # JSON 문자열을 객체로 변환
json_string = '{"이름": "남지후", "나이": 27, "선호장르": ["인문", "소설"]}'
data2 = json.loads(json_string)
print(data2['이름'])
#JSON 파일 쓰기

import json

# 딕셔너리 데이터 준비 (도서 테마)
person_data = {
    "이름": "문하린",
    "나이": 29,
    "직업": "번역가",
    "취미": ["동네책방투어", "보드게임"],
    "주소": {
        "시": "부산",
        "구": "해운대구"
    },
    "최근번역": {"제목": "바닷가의 서점", "언어": "영→한"}
}

# JSON 파일로 저장
with open('json_test.json', 'w', encoding='utf-8') as file:
    json.dump(person_data, file, ensure_ascii=False, indent=2) #dump: 기존 데이터를 버리고 데이터를 바꿔줌

# 문자열로 변환
json_string = json.dumps(person_data, ensure_ascii=False, indent=2)
print(json_string)
# JSON 파일로 저장
with open('person.json', 'w', encoding='utf-8') as file:
    json.dump(person_data, file, ensure_ascii=False, indent=2) #위계를 주기 위해 indent, ascii=알파벳, ascii=False : 알파벳이 아니다

# 문자열로 변환
json_string = json.dumps(person_data, ensure_ascii=False, indent=2)
print(json_string)

 

3) 텍스트 파일 처리

ex) 읽기, 쓰기

# 텍스트 파일 읽기 - 전체 내용
with open('Text_test.txt', 'r', encoding='utf-8') as file:
    content = file.read()
    print(content)
# 텍스트 파일 읽기 - 한 줄씩
with open('Text_test.txt', 'r', encoding='utf-8') as file:
    for line_num, line in enumerate(file, 1): # 컴퓨터는 0번부터 시작하기 때문에 시작 넘버를 입력해줌
        print(f"{line_num}: {line.strip()}")
# 텍스트 파일 쓰기
with open('output.txt', 'w', encoding='utf-8') as file:
    file.write('공지: 오늘 18시에 마감 점검\n')
    file.write('테이블 배치도는 3층 탕비실 보관\n')

# 여러 줄 한 번에 쓰기
    lines = ['사인회 안내문 업데이트\n', '전자책 체험존 점검\n']
    file.writelines(lines)

 

4) 정규표현식

문자들을 가지고 정규 표현식을 어떻게 해석하는가?

 

ex1) 패턴 정의, 찾기, 추출, 치환

import re

text = "연락처: 019-2468-1357, 이메일: booklover@readers.co.kr, 생년월일: 1988-03-12"

# 패턴 정의
phone_pattern = r'\d{3}-\d{4}-\d{4}'# 전화번호 패턴
email_pattern = r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}'# 이메일 패턴
date_pattern = r'\d{4}-\d{2}-\d{2}'# 날짜 패턴
# 첫 번째 매치 찾기
phone = re.search(phone_pattern, text)
if phone:
    print(f"전화번호: {phone.group()}")
# 모든 숫자 추출
numbers = re.findall(r'\d+', text)
print(f"모든 숫자: {numbers}")
# 문자열 치환
masked_text = re.sub(phone_pattern, '010-****-****', text)
print(f"마스킹된 텍스트: {masked_text}")

 

ex2) 사용 예시

import re
96
# 이메일 유효성 검사def is_valid_email(email):
def is_valid_email(email):
    pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
    return bool(re.match(pattern, email))

# 전화번호 형식 통일def format_phone_number(phone):
def format_phone_number(phone):
    numbers = re.sub(r'[^0-9]', '', phone)# 숫자만 추출
    if len(numbers) == 11:
        return f"{numbers[:3]}-{numbers[3:7]}-{numbers[7:]}"
    return phone

# HTML 태그 제거def remove_html_tags(text):
def remove_html_tags(text):
    return re.sub(r'<[^>]+>', '', text)

# 사용 예시
print(is_valid_email("paper.shop@example.com")) # True
print(format_phone_number("0198765432")) # 019-9876-5432
print(remove_html_tags("<div>사인회 공지</div>")) # 사인회 공지

 

ex3) with 문을 활용하자

# 권장: with 문 사용
with open('notice.txt', 'r', encoding='utf-8') as file:
    content = file.read()
# 블록이 끝나면 자동으로 파일이 닫힘

# 비권장: 수동으로 파일 닫기
file = open('notice.txt', 'r', encoding='utf-8')
try:
    content = file.read()
finally:
    file.close()# 실수로 빠뜨리기 쉬움

# 기본적으로 with를 사용하면 블록이 끝난 후 자동으로 파일이 닫힘

 

ex4) 추가적인 테크놀로지아

# 두 개의 파일을 동시에 열기
with open('event_source.txt', 'r', encoding='utf-8') as infile, \
     open('event_upper.txt', 'w', encoding='utf-8') as outfile:
 
#백슬러시를 쓰면 여러개를 더하는거
    for line in infile:
        processed_line = line.upper()# 대문자로 변환
        outfile.write(processed_line)

# 파일 복사 예제def copy_file(source, destination):
    with open(source, 'r', encoding='utf-8') as src, \
         open(destination, 'w', encoding='utf-8') as dst:
        dst.write(src.read())

 

 

3. (라이브세션) [데이터 전처리&시각화] 시각화 기초

1) 중복 데이터 처리

ex1) 거래 데이터(랜덤) 생성

import numpy as np
import pandas as pd

# 거래 데이터 생성 (의도적 중복 포함)
np.random.seed(123)

# 기본 거래 데이터
base_trades = pd.DataFrame({
    'trade_id': range(1, 21),
    'stock_symbol': np.random.choice(['AAPL', 'MSFT', 'GOOGL'], 20),
    'trade_date': pd.date_range('2024-01-01', periods=20, freq='D'),
    'quantity': np.random.randint(100, 1000, 20),
    'price': np.round(np.random.uniform(100, 200, 20), 2)
})

# 중복 데이터 생성 (시스템 오류 시뮬레이션, 실무에선 이거 안넣어요~)
duplicate_trades = base_trades.iloc[[2, 5, 8, 15]].copy()# 일부 행 복사
duplicate_trades['trade_id'] = [101, 102, 103, 104]# ID만 변경# 완전 동일한 중복도 추가
exact_duplicate = base_trades.iloc[[10, 12]].copy()

# 모든 데이터 결합
trades_df = pd.concat([base_trades, duplicate_trades, exact_duplicate], ignore_index=True)

print("중복이 포함된 거래 데이터:")
print(f"전체 데이터 행 수: {len(trades_df)}")
trades_df
 
중복이 포함된 거래 데이터: 전체 데이터 행 수: 26 

# 표는 생략

 

ex2) 중복 행 확인

# 중복 행 확인
trades_df.duplicated() # 내가 확인할 중복 데이터

# 해당 값 적용 시 중복 값이 True 형태로 산출됨

# 1행, 2행, 3행이 중복이라고 하면, 1행은 False값, 2 3행은 True로 나옴

   항상 첫번째 중복 값은 True

 

ex3) 중복된 데이터가 있는 행을 보여조

trades_df[trades_df.duplicated()]
trades_df.duplicated(keep=False) # 전체에 대해서 중복값 확인

#keep = False이면 중복값이 True

trades_df[trades_df.duplicated(keep=False)] #실제 중복되는 행들이 어디에 있는지

 

ex4) 중복값 제거

trades_df.drop_duplicates()

# 결측치 제거할 때도 썼던 drop -> 중복된 행이 사라짐

 

ex5) 특정 컬럼 기준으로 중복 제거

trades_df.drop_duplicates(subset=['stock_symbol', 'trade_date'])

# 다른 컬럼은 무시하고, subset으로 지정해둔 stock_symbol열과 trades_date 열이 같으면 중복되는 항목을 날림

 

ex6) 중복 제거 전략

ex6-1) 최근 값만 남기기

latest_trades = trades_df.drop_duplicates(
    subset=['stock_symbol', 'trade_date'],
    keep='last'
)
latest_trades
 
trades_df[trades_df.duplicated(subset = ['stock_symbol', 'trade_date'], keep='last')]

 

ex6-2) 최대 값만 남기기

trades_df.sort_values('quantity', ascending=False).reset_index()

# ascending = True: 오름차순, False: 내림차순

# reset_index를 추가하여 정렬 및 필터링 후 다시 0부터 번호 매김, 기존 index는 남아있음

 

2) 시각화

- 데이터 시각화: 숫자와 텍스트로 이루어진 데이터를 차트, 그래프, 지도 등 시각적 요소로 표현하는 과정을 의미

 

- 탐색적 데이터 분석(EDA): 데이터 탐정 작업, 새로운 데이터를 받았을 때 모델링 전 데이터가 어떻게 생겼는지, 어던 특징이 있는지, 어떤 문제가 있는지 파악하는 과정

 

- EDA의 목표

     a. 이 데이터가 무엇을 담고 있는가?

    b. 어떤 관련성이 있는가?

    c. 결측치, 이상치, 오류가 있는가?

    d. 분석 방향성을 어떻게 잡아야 하는가?

 

- EDA에서 시각화의 역할

    a. 데이터의 분포를 파악

    b. 변수 간의 관계를 발견

    c. 결측치 패턴을 확인

    d. 이상치(outliner)를 탐지

    e. 가설 생성과 검증을 지원

 

ex1) matplotlib

import matplotlib.pyplot as plt
# x축 데이터와 y축 데이터 준비
x = [1, 2, 3, 4, 5]
y = [10, 20, 25, 30, 35]
plt.plot(x,y) #x 축에는 x를, y 축에는 y 값들을 넣어러


plt.xlabel('온도')  # X축 이름 설정
plt.ylabel('습도')  # Y축 이름 설정
plt.title('즈에에모오옥')  # 플롯 제목 설정

plt.plot(x,y, label = 'FT1')
plt.legend() #범레

plt.plot(x,y)

 

ex2) pyplot과 객체 지향 인터페이스

ex2-1) pyplot

# pyplot 인터페이스
import matplotlib.pyplot as plt

# 데이터 준비
x = [1, 2, 3, 4, 5]
y = [10, 20, 25, 30, 35]

# 플롯 생성 및 스타일 추가
plt.plot(x, y, label='샘플 데이터', color='blue', linestyle='--', marker='x') #객체지향하고 이부분이 차이남. 

# 레이블, 제목, 범례 추가
plt.xlabel('X축 이름')
plt.ylabel('Y축 이름')
plt.title('pyplot 인터페이스 예시')
plt.legend()

# 플롯 표시
plt.show()

# 자동이라고 생각하면 됨. 

 

ex2-2) 객체 지향 인터페이스

#객체 지향 인터페이스
import matplotlib.pyplot as plt

# 데이터 준비
x = [1, 2, 3, 4, 5]
y = [10, 20, 25, 30, 35]

# 캔버스와 축 생성
fig, ax = plt.subplots() # 캔버스와 축을 직접 입력하여 생성해야함

# 축(ax) 객체에 직접 플롯 추가
ax.plot(x, y, label='샘플 데이터', color='blue', linestyle='--', marker='x') #pyplot은 plt로 시작, 객체지향은 ax로 시작

# 축, 제목, 범례 추가
ax.set_xlabel('X축 이름')
ax.set_ylabel('Y축 이름')
ax.set_title('객체 지향 인터페이스 예시')
ax.legend()

# 플롯 표시
plt.show()

# 수동으로 설정해 주어야 하는 내용들이 많음. but 세부적으로 조절할 수 있음

 

ex3) bar형 플롯

ex3-1) pyplot

categories = ['A','B','C','D']
values = [10, 20, 30, 40]

plt.bar(categories, values, color = 'green')
plt.show()

 

ex3-2) 객체 지향

categories = ['A','B','C','D']
values = [10, 20, 30, 40]

fig, ax = plt.subplots()
ax.bar(categories, values)
plt.show()

 

ex4) scatter plot: 두 변수 간의 상관관게를 탐색할 때 사용

 

ex4-1) pyplot

x = [5, 7, 8, 7, 2, 17, 2, 9, 4, 11, 12, 9, 6]
y = [99, 86, 87, 88, 100, 86, 103, 87, 94, 78, 77, 85, 86]

plt.scatter(x, y)
plt.show()

 

ex4-2) 객체 지향

fig, ax = plt.subplots()
x = [5, 7, 8, 7, 2, 17, 2, 9, 4, 11, 12, 9, 6]
y = [99, 86, 87, 88, 100, 86, 103, 87, 94, 78, 77, 85, 86]

ax.scatter(x, y)
plt.show()

 

ex5) 히스토그램

import numpy as np
import matplotlib as mpl
mpl.rcParams['axes.unicode_minus'] = False     #마이너스 깨짐 방지, 이건 안외워도 됨ㅋㅋ
data = np.random.randn(1000)

plt.hist(data, bins=30)
plt.show()

# bins: 구간, bin값이 커지면 더 많은 구간을 히스토그램에 담을 수 있음

 

ex6) pie chart

sizes = [10, 20, 25, 30]
labels = ['A', 'B', 'C', 'D']

plt.pie(sizes , labels=labels, autopct='%1.2f%%') #1f면 소숫점 첫째
plt.show()

 

 

ex7) stack plot(누적형)

 

ex7-1) pyplot

x = [1, 2, 3, 4, 5]
y1 = [1, 1, 2, 3, 5]
y2 = [0, 4, 2, 6, 8]
y3 = [1, 3, 5, 7, 9]
 
plt.stackplot(x, y1, y2, y3, labels=['Y1', 'Y2', 'Y3'])
plt.legend(loc='upper left') # 이건 범례 위치임
plt.show()

 

ex7-2) 객체 지향

fig, ax = plt.subplots()
x = [1, 2, 3, 4, 5]
y1 = [1, 1, 2, 3, 5]
y2 = [0, 4, 2, 6, 8]
y3 = [1, 3, 5, 7, 9]

ax.stackplot(x, y1, y2, y3, labels=['Y1', 'Y2', 'Y3'])
ax.legend(loc='upper left')
plt.show()

 

ex8) box plot(중요중요)

data = np.random.rand(10, 4)
plt.boxplot(data)
plt.show()

    # 주황선: 중앙값

    # box의 위 경계/아래 경계: describe()를 통해 나온 75%값/ 25% 값

    # 선 위/아래: 상위/하위 경계 내측의 최대/최솟값

    # o: 아웃라이어, 이상치

    # box: IQR

 

ex9) violin plot: 박스플롯과 비슷하지만 데이터 분포 및 밀도를 확인 할 수 있음.

data = np.random.rand(10, 4)
plt.violinplot(data)
plt.show()

 

3) 그래프 커스터마이징

 

ex1) pyplot

# 데이터 생성
x = [1, 2, 3, 4]
y = [10, 25, 30, 15]

# 그래프 사이즈 설정
plt.figure(figsize=(4, 3))

# 그래프 그리기
plt.plot(x, y)

# 제목 설정
plt.title("그래서그게뭔데", fontsize=14, fontweight='bold', color='blue', loc = 'left')
 
# X축 레이블 설정
plt.xlabel("X Axis Label", fontsize=12, color='red')

# Y축 레이블 설정
plt.ylabel("Y Axis Label", fontsize=12, color='blue')
 
# 축 범위 지정
plt.xlim(0, 5) # X축의 범위를 0부터 5까지 지정
plt.ylim(5, 35) # Y축의 범위를 5부터 35까지 지정
plt.gca().invert_yaxis()
 
# X축과 Y축 눈금 설정
plt.xticks([1, 2, 3, 4], ['One', 'Two', 'Three', 'Four'])
plt.yticks([10, 20, 25, 30], ['Ten', 'Twenty', 'Twenty-Five', 'Thirty'])
 
# 그리드 설정
plt.grid(True, which='both', axis='both', color='red', linestyle='-.', linewidth=2)

ex2) 객체지향

# Figure와 Axes 객체 생성 및 그래프 사이즈 설정
fig, ax = plt.subplots(figsize=(4, 3))

# 데이터를 그래프로 표현
ax.plot(x, y)

# X축 레이블 설정
ax.set_xlabel("X Axis Label", fontsize=12, color='red')

# Y축 레이블 설정
ax.set_ylabel("Y Axis Label", fontsize=12, color='blue')
 
# 축 범위 지정
ax.set_xlim(0, 5) # X축의 범위를 0부터 5까지 지정
ax.set_ylim(5, 35) # Y축의 범위를 5부터 35까지 지정
 
# X축과 Y축 눈금 설정
ax.set_xticks([1, 3, 4])
ax.set_xticklabels(['One', 'Three', 'Four'])
ax.set_yticks([10, 20, 25, 30])
# ax.set_yticklabels(['Ten', 'Twenty', 'Twenty-Five', 'Thirty'])
 
# 그리드 설정
ax.grid(True, which='both', axis='both', color='gray', linestyle='-', linewidth=0.5)
 

# 그래프 표시
plt.show()

 

4. 데이터 전처리& 시각화 3주차

A. 데이터 불러오기/저장하기

1) 데이터 불러오기

import pandas as pd
import seaborn as sns

#판다스, 시본 사용 선언

.

data.to_csv("tips_data.csv", index=False

# 현재 위치에 이 파일을 만들 것이다...!

# 별도의 인덱스를 지정해주지 않으면 인덱스가 컬럼의 형태로 들어오게 됨. index=False 구절 필요

        index_col = 0 을 사용해도 같은 입력임

 

df = pd.read_csv("tips_data.csv")
df

# 위에서 만든 파일 불러오기

 

2) 데이터 저장하기

df = pd.read_csv("tips_data.csv", index_col=0)

# 파일을 불러옴, 인덱스가 칼럼으로 들어오는걸 방지

 

df.to_excel("tips_data.xlsx", index=False)

#불러온 파일을 엑셀로 저장

 

print(os.getcwd())

# 저장 위치를 알려주세용

 

3) 인덱스

 

다음과 같은 데이터프레임을 만들었음.

df = pd.DataFrame({
    'A': [1,2,3],
    'B': ['a','b','c']
}, index = ['idx1','idx2','idx3'])

 

  A B
idx1 1 a
idx2 2 b
idx3 3 c

 

df.loc['idx2'
 
A 2 B b Name: idx2, dtype: object

# 두번째 행을 가져오게 됨

df.sort_index()

#정렬정렬

 

df.set_index('A') # A란느 컬럼을 쓸거임

#칼럼 A에 있는 값들을 가져옴

 

df.index #인덱스 값이 어떻게 이루어져 있는지
 
Index(['idx1', 'idx2', 'idx3'], dtype='object')

# index값이 어떻게 이루어져 있는지 확인

 

df.index = ['a', 'b','c']
df
  A B
a 1 a
b 2 b
c 3 c

 

#인덱스를 바꿔줌

 

df.reset_index(drop=True)

#바꾼걸 초기화

 

4) 컬럼

다음의 데이터 프레임을 만듦

data = {
    'name': ['Alice', 'Bob', 'Charlie'],
    'age' : [25, 30, 25],
    'gender': ['female','male','male']
}

df = pd.DataFrame(data)
df
  name age gender
0 Alice 25 female
1 Bob 30 male
2 Charlie 25 male

 

df['name']
 
0 Alice 1 Bob 2 Charlie Name: name, dtype: object

# name 컬럼에 있는 값 가져옴

df.columns
 
Index(['name', 'age', 'gender'], dtype='object')

#각 컬럼이 뭔지 가져옴

 

df.columns = ['이름','나이','성별'
df

# 각 컬럼 이름을 바꿔줌

df.rename(columns = {'나이':'age', '성별': '남/여'})

# 지정해서 바꿔줌

df['스포츠'] = '축구'

#새로운 컬럼을 추가해줌

del df['스포츠'

#컬럼을 지워줌

 

B. 데이터 확인하기

1) head, info, describe

일단 사용하고자 하는 데이터를 불러와 변수에 저장하기

df = pd.read_csv("tips_data.csv" )

 

df.head(30)

#위에서부터 30줄만

 

df.info(30)

# 전반적인 정보: 인덱스 갯수, 컬럼 이름, null 카운트, 데이터 타입

 

df.describe()

#통계적인 정보: count, mean, std, min, 25%, 50%, 75%, max, min

 

2) 결측치 확인하기

df.isna()

# null 값을 True로 반환하는 메소드 -> True가 있다? null 값 있다

 

df[df['B'].isna()]

# 특정 컬럼 내에서만 null값을 True로 반환

 

3) 데이터 타입

info()를 통해 컬럼 내의 데이터가 어떤 타입인지 알 수 있다.

df['total_bill'].dtype

#특정 칼럼을 지정하여 데이터 타입을 확인함

 

df['totL_bill'] = df['total_bill'].astype(str)

# 실수형 데이터를 문자열로 바꿔줌 - astype

 

C. 데이터 선택

1) iloc

다음과 같은 데이터 프레임을 만듦

df = pd.DataFrame({
    'A': [1,2,3,4,5],
    'B': [10,20,30,40,50],
    'C': [100,200,300,400,500]
})
df
  A B C
0 1 10 100
1 2 20 200
2 3 30 300
3 4 40 400
4 5 50 500

 

df.iloc[0:5:2

#iloc은 [start:end:term] 구조로 쓴다

  A B C
0 1 10 100
2 3 30 300
4 5 50 500

 

df.iloc[0,0:2
A 1 B 10 Name: 0, dtype: int64

#iloc의 0(첫번 째 행)의 첫 열부터 2 전까지, 즉 0번째 1번째인 A, B 컬럼만

 

df = pd.DataFrame({
    'A': [1,2,3,4,5],
    'B': [10,20,30,40,50],
    'C': [100,200,300,400,500]
}, index = ['a','b','c','d','e']) 
df
  A B C
a 1 10 100
b 2 20 200
c 3 30 300
d 4 40 400
e 5 50 500

# 인덱스를 추가한 것, 추가하지 않으면 자동으로 숫자 인덱스가 매겨짐

 

※ loc는 라벨 기반, iloc는 정수 기반

df.iloc[:,0]
 
a 1
b 2
c 3
d 4
e 5
Name: A, dtype: int64

# 행 전체(그냥 : 달랑), 0번째 열만, 1: 이면 맨 첫줄(0번) 제외

 

df.loc['b':,'A']
 
b 2
c 3
d 4
e 5
Name: A, dtype: int64

# b열부터, A 칼럼만

 

- loc는 라벨 기반, iloc는 정수 기반

 

2). Slicing, selection

아래의 데이터 프레임에서

  A B C
a 1 10 100
b 2 20 200
c 3 30 300
d 4 40 400
e 5 50 500

 

df.loc['a':'b',['A','C']]
  A C
a 1 100
b 2 200

 

# a부터 b 열 까지 자르고, A,C 컬럼만

 

3) boolean indexing

아까 사용했던 파일을 불러오자.

df[df['sex'] == 'Male']

#불리언 인덱싱: 조건이 참인 경우를  가져옴, 즉 성별이 남성인 데이터만 가져옴

 

df[(df['sex'] == 'Male') & (df['smoker'] == 'Yes')] #and 조건

# and 조건을 적용한 불리언 인덱싱, 성별이 남성이고 흡연자인 교집합을 가져옴

 

df[(df['sex'] == 'Male') | (df['smoker'] == 'Yes')] #or 조건, shift+\

# or 조건을 적용한 불리언 인덱싱, 성별이 남성이거나 흡연자인 경우를 가져옴.

 

df.loc[df['size']>3, ['tip','total_bill']] #슬라이싱을 하지 않고 두 컬럼을 보는 법

# 슬라이싱을 하지 않고 두 컬럼ㅇ르 보는 법.

# size가 3보다 큰 열의 tip과 total bill 컬럼을 보여줌

 

df[df['size'].isin([1,2])]

#isin 메소드, size 컬럼의 각 값이 1, 2 둘 중 하나인지 확인하여 가져옴

 

D. 데이터 병합

 

1) concat

상하좌우 축을 입력하여 병합

 

다음 데이터프레임을 생성

df1 = pd.DataFrame({
    'A': ['A0', 'A1', 'A2', 'A3'],
    'B': ['B0', 'B1', 'B2', 'B3'],
    'C': ['C0', 'C1', 'C2', 'C3'],
    'D': ['D0', 'D1', 'D2', 'D3']
    })

df2 = pd.DataFrame({
    'A': ['A4', 'A5', 'A6','A7'],
    'B': ['B4', 'B5', 'B6','B7'],
    'C': ['C4', 'C5', 'C6','C7'],
    'D': ['D4', 'D5', 'D6','D7']
})

df3 = pd.DataFrame({
    'A': ['A8', 'A9', 'A10','A11'],
    'B': ['B8', 'B9', 'B10','B11'],
    'C': ['C8', 'C9', 'C10','C11'],
    'D': ['D8', 'D9', 'D10','D11']
})
 

 

df = pd.concat([df1, df2, df3], axis = 0).reset_index(drop=True)

# concat: 이어붙이기

# axis = 0: 행 방향으로 붙이기

# axis = 1: 열 방향으로 붙이기

# reset_index: 인덱스 다시 매기기

# drop=True: 기존 인덱스는 버림

 

합치면서 빈 값이 있으면 null로 채움

 

2) merge

특정 칼럼을 고려해서 병합

 

다음 데이터프레임을 생성

# 두 개의 데이터프레임 생성
left_df = pd.DataFrame({
    'key': ['A', 'B', 'C', 'D'],
    'value': [1, 2, 3, 4]
    })

right_df = pd.DataFrame({
    'key': ['B', 'D', 'E', 'F'],
    'value': [5, 6, 7, 8]
    })

print(left_df)
print(right_df)

 

pd.merge(left_df, right_df, on = 'key', how = 'right')

# left_df 값이 변경되지 않으면서 left_df(value_x)에 속하는 값을 보여줌

 

E. 데이터 집계

 

다음의 데이터 프레임 생성

df6 = pd.DataFrame({
    'Category': ['A', 'B', 'A', 'B', 'A', 'B'],
    'Value': [1, 2, 3, 4, 5, 6]
})
df6
df6.groupby('Category') #오브젝트 형성
df6.groupby('Category').sum()
df6.groupby('Category').count()
df6.groupby('Category').max()
df6.groupby('Category').min()
df6.groupby('Category').first() #첫번째 값
df6.groupby('Category').agg(list) #aggregation, 집계

  Value
Category  
A [1, 3, 5]
B [2, 4, 6]

- 피벗테이블

'빅데이터 QAQC_3기 > 빅데이터 QAQC_3기 TIL' 카테고리의 다른 글

TIL_251001  (0) 2025.10.01
TIL_250930  (0) 2025.09.30
TIL_250926  (0) 2025.09.26
TIL_250925  (0) 2025.09.25
TIL_250924  (0) 2025.09.24