Pandas CSV 불러오기 — 데이터를 받으면 가장 먼저 확인해야 할 것들

2026. 8. 23. 16:52·AI Journey/Pandas
728x90
반응형

CSV를 열었다면 분석부터 하지 마세요

 

 

이번 글부터 Pandas와 데이터 시각화 과정에서 공통으로 사용할 ai_learning_dataset.csv 파일을 사용합니다.
예제를 직접 실행하려면 아래의 실습 파일을 준비해주세요.

ai_learning_dataset.csv
0.00MB

 

지난 글에서는 Pandas가 왜 필요한지 알아보았습니다.

NumPy가 숫자의 배열을 효율적으로 계산하는 데 강하다면,

Pandas는 의미를 가진 표 형태의 현실 데이터를 다루는 데 강한 도구였습니다.
그리고 Pandas의 핵심 자료구조인 DataFrame도 만들어봤습니다.

이제 실제 데이터를 가져와보겠습니다.

우리가 사용할 파일은 다음과 같습니다.

ai_learning_dataset.csv

그런데 파일을 받았다고 바로 평균을 계산하거나 그래프를 그리기 시작해도 될까요?

아닙니다.

새로운 데이터를 받으면 먼저 해야 할 일이 있습니다.
내가 받은 데이터가 어떻게 생겼는지 확인하는 것입니다.

 


CSV란 무엇일까?

우리가 사용할 파일의 확장자는 .csv입니다.

CSV는 Comma-Separated Values의 약자입니다.
이름 그대로 데이터를 쉼표로 구분해 저장할 수 있는 텍스트 형식입니다.

예를 들어 다음과 같습니다.

student_id,age,study_hours,attendance_rate,course,city,passed
1001,39,15.8,94.6,Python,Daegu,1
1002,25,12.8,85.5,AI,Daejeon,1
1003,37,9.0,100.0,AI,Incheon,1
첫 번째 줄은 각 Column의 이름입니다.
student_id
age
study_hours
attendance_rate
course
city
passed

그 아래부터 실제 데이터가 들어갑니다.

CSV 파일을 직접 텍스트 편집기로 열면 이런 구조를 볼 수 있습니다.
하지만 데이터가 수천 행, 수십만 행으로 늘어난다면 사람이 직접 읽는 방식은 현실적이지 않습니다.
그래서 Pandas를 사용합니다.

 


Pandas로 CSV 불러오기

먼저 Pandas를 불러옵니다.

import pandas as pd

그리고 read_csv()를 사용합니다.

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

코드를 해석하면 매우 단순합니다.

pd
↓
Pandas

read_csv()
↓
CSV 파일 읽기

df
↓
읽어온 DataFrame을 저장할 변수

즉,

CSV 파일
↓
pd.read_csv()
↓
DataFrame

으로 변환된 것입니다.

#35에서 직접 만들었던 DataFrame과 달리 이번에는 외부 파일에 저장된 데이터를 DataFrame으로 가져왔습니다.

 


파일 경로는 어디를 기준으로 할까?

처음 read_csv()를 사용할 때 자주 만나는 문제가 있습니다.
df = pd.read_csv("ai_learning_dataset.csv")
이 코드는 Python이 현재 작업하고 있는 위치에서 해당 파일을 찾습니다.
파일을 찾지 못하면 다음과 같은 오류를 만날 수 있습니다.
FileNotFoundError
이 오류가 발생했다면 Pandas가 고장 난 것이 아니라 대부분은 파일 경로를 확인해야 한다는 의미입니다.

예를 들어 CSV가 data 폴더 안에 있다면

df = pd.read_csv("data/ai_learning_dataset.csv")

처럼 경로를 지정할 수 있습니다.

이번 시리즈에서는 복잡한 파일 경로 처리를 공부하지 않습니다.

CSV 파일과 Python 코드 또는 Notebook을 같은 작업 위치에 두고 진행하면 충분합니다.

 


데이터를 전부 출력해봐야 할까?

CSV를 읽었습니다.

그렇다면 다음처럼 실행하면 어떨까요?

print(df)

물론 가능합니다.

하지만 데이터가 10만 행이라면 어떨까요?
모든 데이터를 출력하는 것은 좋은 방법이 아닙니다.

 

우리가 먼저 알고 싶은 것은 전체 데이터 하나하나가 아닙니다.

대략 어떻게 생긴 데이터인가?

입니다.

이럴 때 가장 먼저 사용할 수 있는 것이 head()입니다.

 


head() — 데이터 앞부분 확인하기

다음 코드를 실행해보겠습니다.

df.head()
print(df.head())

기본적으로 DataFrame의 앞부분 5개 행을 보여줍니다.

우리 데이터에서는 다음과 같은 형태를 확인할 수 있습니다.

   student_id  age  study_hours  attendance_rate  assignment_score  previous_score  course      city  passed
0        1001   39         15.8             94.6             100.0            74.2  Python     Daegu       1
1        1002   25         12.8             85.5              88.0            90.2      AI   Daejeon       1
2        1003   37          9.0            100.0              85.9            74.4      AI   Incheon       1
3        1004   21         19.2             77.1             100.0            81.8  Python   Daejeon       1
4        1005   31         13.6             88.0              80.8            56.7  Python     Busan       1

이것만으로도 꽤 많은 정보를 얻을 수 있습니다.

어떤 Column이 있는가?

값은 대략 어떤 형태인가?

숫자와 문자열이 어떻게 섞여 있는가?

한 행이 무엇을 나타내는가?
head()는 단순히 앞의 다섯 줄을 보는 함수라기보다
처음 만난 데이터의 생김새를 빠르게 확인하는 도구입니다.

원하는 개수를 지정할 수도 있습니다.

print(df.head(3))

그러면 앞의 3개 행만 확인합니다.

 


shape — 데이터는 얼마나 클까?

다음으로 데이터의 크기를 확인해보겠습니다.

NumPy에서도 이미 shape를 배웠습니다.

Pandas DataFrame에서도 사용할 수 있습니다.

df.shape
print(df.shape)

결과는 다음과 같습니다.

(82, 9)

NumPy에서 배웠던 것처럼

(행, 열)

순서입니다.

따라서 현재 DataFrame은

82개의 Row
9개의 Column

을 가지고 있습니다.

여기서 중요한 습관이 하나 있습니다.
데이터를 받으면 전체 크기를 먼저 확인한다.

예를 들어 원래 10,000명의 데이터라고 들었는데

df.shape

결과가

(823, 20)

이라면 뭔가 이상하다는 것을 바로 알 수 있습니다.

shape는 단순한 숫자 확인이 아니라
내가 예상한 데이터와 실제 데이터가 맞는지 검증하는 첫 번째 단서가 됩니다.

 


잠깐, 왜 학생이 80명인데 82행일까?

이번 데이터셋은 약 80명의 학습자 데이터를 사용한다고 했습니다.

그런데 shape는

(82, 9)

입니다.

왜 82개의 Row가 있을까요?

지금 바로 원인을 찾아내지는 않겠습니다.

다만 이 사실은 기억해두겠습니다.

예상
약 80명

실제
82 Row
데이터를 분석할 때는 이런 작은 차이를 그냥 지나치지 않는 습관이 중요합니다.

뒤에서 다시 확인해보겠습니다.

 


어떤 Column이 있는지 확인하기

이번에는 Column 이름을 확인해보겠습니다.

df.columns
print(df.columns)

결과는 다음과 같은 형태입니다.

Index(['student_id', 'age', 'study_hours', 'attendance_rate',
       'assignment_score', 'previous_score', 'course', 'city',
       'passed'],
      dtype='object')

총 9개의 Column이 있습니다.

student_id
age
study_hours
attendance_rate
assignment_score
previous_score
course
city
passed
Column 이름을 확인하는 것은 생각보다 중요합니다.

실제 데이터에서는

Age
age
student_age
studentAge
예상과 다른 이름을 사용하는 경우도 있기 때문입니다.
심지어 눈에 잘 보이지 않는 공백이 포함되어 있을 수도 있습니다.
따라서 코드를 작성하기 전에 실제 Column 이름부터 확인하는 것이 좋습니다.

 


dtypes — 각 Column에는 어떤 자료형이 들어 있을까?

NumPy에서 dtype의 중요성을 배웠습니다.

Pandas에서도 자료형은 중요합니다.
DataFrame에는 여러 Column이 있기 때문에

각 Column마다 서로 다른 dtype을 가질 수 있습니다.

확인해보겠습니다.

df.dtypes
print(df.dtypes)

우리 데이터에서는 대략 다음과 같은 결과를 볼 수 있습니다.

student_id            int64
age                 float64
study_hours         float64
attendance_rate     float64
assignment_score    float64
previous_score      float64
course               object
city                 object
passed                int64
dtype: object

여기서 흥미로운 점이 있습니다.

student_id는 정수입니다.

int64

study_hours는 소수점이 있으므로

float64

입니다.

course, city처럼 문자열 데이터가 들어 있는 Column은 여기서는

object

로 보입니다.

 


그런데 age는 왜 float64일까?

여기서 이상한 점 하나를 발견할 수 있습니다.

나이는 다음처럼 보입니다.

39
25
37
21
31

전부 정수처럼 보입니다.

그런데 Pandas가 확인한 dtype은

float64

입니다.

왜일까요?

아직 답을 확인하지 않고 질문만 남겨두겠습니다.

정수처럼 보이는 age가 왜 float64로 읽혔을까?
데이터의 dtype이 예상과 다르다는 것은 데이터 안에 우리가 아직 확인하지 못한 무언가가 있다는 신호일 수 있습니다.

 


info() — DataFrame 전체 상태를 한 번에 확인하기

지금까지 여러 가지를 따로 확인했습니다.

df.shape
df.columns
df.dtypes
Pandas에는 DataFrame의 기본적인 상태를 한 번에 살펴볼 수 있는 매우 유용한 기능도 있습니다.
df.info()

실행하면 다음과 비슷한 정보가 출력됩니다.

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 82 entries, 0 to 81
Data columns (total 9 columns):
 #   Column             Non-Null Count  Dtype
---  ------             --------------  -----
 0   student_id         82 non-null     int64
 1   age                79 non-null     float64
 2   study_hours        82 non-null     float64
 3   attendance_rate    82 non-null     float64
 4   assignment_score   79 non-null     float64
 5   previous_score     80 non-null     float64
 6   course             82 non-null     object
 7   city               82 non-null     object
 8   passed             82 non-null     int64

처음 보면 정보가 많아 보입니다.

하지만 하나씩 보면 어렵지 않습니다.

 


RangeIndex

먼저 다음 부분입니다.

RangeIndex: 82 entries, 0 to 81

총 82개의 행이 있고 Index가

0 ~ 81

까지 있다는 의미입니다.

#35에서 DataFrame 왼쪽에 붙어 있던 숫자를 기억하시나요?

0
1
2
...

바로 그 Index입니다.

 


Data columns

다음은

Data columns (total 9 columns)

입니다.

총 9개의 Column이 있다는 뜻입니다.

이것은 앞에서 확인했던

df.shape

의 두 번째 값과도 연결됩니다.

(82, 9)
     ↑
   Column

서로 다른 명령어의 결과가 같은 데이터 구조를 설명하고 있습니다.

 


Non-Null Count가 중요하다

이번에는 다음 부분을 보겠습니다.

student_id         82 non-null
age                79 non-null
study_hours        82 non-null
attendance_rate    82 non-null
assignment_score   79 non-null
previous_score     80 non-null
course             82 non-null
city               82 non-null
passed             82 non-null

전체 Row는 82개입니다.

 

그런데 age는

79 non-null

입니다.

무언가 이상합니다.
82개의 Row가 있는데 값은 79개만 존재합니다.

계산해보면

82 - 79 = 3
즉 age에는 값이 없는 데이터가 3개 있다는 것을 알 수 있습니다.
assignment_score도 마찬가지입니다.
82 - 79 = 3

previous_score는

82 - 80 = 2

입니다.

우리가 아직 데이터 전체를 하나하나 살펴보지 않았는데도 info()만으로 중요한 문제를 발견했습니다.

 


비어 있는 값, 결측치

데이터에 값이 존재하지 않는 경우를 결측치(Missing Value)라고 합니다.

 

student_id | age | study_hours
--------------------------------
1001       | 39  | 15.8
1002       |     | 12.8
1003       | 37  | 9.0

예를 들어, 위와 같이 age가 비어 있을 수 있습니다.

Pandas에서는 상황에 따라 이런 값을 NaN, NA 등의 형태로 만나게 됩니다.

그리고 이것이 앞에서 발견했던 질문과 연결됩니다.

age는 정수처럼 보이는데
왜 float64였을까?

이번 CSV를 읽었을 때 age에는 비어 있는 값이 있습니다.

따라서 우리가 눈으로 본 몇 개의 값만 가지고 Column 전체의 상태를 판단해서는 안 됩니다.

데이터의 일부가 아니라 Column 전체의 dtype과 결측 상태를 함께 확인해야 합니다.

결측치를 실제로 어떻게 찾고 처리할지는 #38에서 자세히 다루겠습니다.

지금은 문제가 존재한다는 사실을 발견하는 것이 목표입니다.

 


head()만 봤다면 발견했을까?

여기서 중요한 점이 있습니다.

우리가 처음 실행한 것은

df.head()

였습니다.

앞의 5개 Row는 꽤 정상적으로 보였습니다.

그것만 보고 "데이터가 잘 들어왔네." 라고 판단했다면 결측치를 발견하지 못했을 수도 있습니다.
그래서 하나의 명령어만 보고 데이터를 판단하면 안 됩니다.

각각 확인하는 것이 다릅니다.

head()
↓
데이터가 어떻게 생겼는가?

shape
↓
얼마나 많은 데이터가 있는가?

columns
↓
어떤 항목이 있는가?

dtypes
↓
각 Column은 어떤 자료형인가?

info()
↓
전체 구조와 값의 존재 상태는 어떠한가?

 명령어들이 서로 보완합니다.

 


데이터를 받았을 때의 기본 루틴

앞으로 새로운 CSV 데이터를 받았다면 다음 순서를 하나의 습관으로 만들어도 좋습니다.

import pandas as pd

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

df.head()
df.shape
df.columns
df.dtypes
df.info()

무조건 이 순서대로 실행해야 한다는 규칙은 아닙니다.

하지만 처음 데이터를 파악하기 위한 좋은 출발점입니다.

이를 질문으로 바꾸면 더욱 이해하기 쉽습니다.

1. 제대로 읽혔나?
        ↓
   read_csv()

2. 어떻게 생겼나?
        ↓
   head()

3. 얼마나 큰가?
        ↓
   shape

4. 어떤 항목이 있나?
        ↓
   columns

5. 어떤 자료형인가?
        ↓
   dtypes

6. 빠진 값은 없는가?
        ↓
   info()

 

중요한 것은 함수 이름을 외우는 것이 아닙니다.
데이터를 분석하기 전에 먼저 데이터의 상태를 확인한다.
이 습관을 만드는 것입니다.

 


데이터에 대한 몇 가지 의문점

아직 제대로 데이터 분석을 시작하지도 않았습니다만
몇 줄의 코드만으로 몇 가지 질문이 생겼습니다.

첫 번째,

학생 데이터가 약 80명인데
왜 Row는 82개일까?

두 번째,

age는 왜 82개가 아니라
79개의 값만 있을까?

세 번째,

assignment_score는
왜 79개뿐일까?

네 번째,

previous_score는
왜 80개뿐일까?

그리고

age는 정수처럼 보이는데
왜 float64일까?

라는 질문도 있습니다.

 

이것이 바로 데이터 탐색(EDA, Exploratory Data Analysis)의 시작입니다.

 


발견과 해결을 구분하자

여기서 바로 데이터를 수정하고 싶을 수도 있습니다.

예를 들어 값이 비어 있다면

삭제할까?
평균을 넣을까?
0을 넣을까?

같은 생각이 들 수 있습니다.

하지만 아직은 하지 않겠습니다.

왜냐하면

문제를 발견하는 것과 문제를 어떻게 처리할지 결정하는 것은 서로 다른 단계

이기 때문입니다.

결측값이라고 해서 무조건 삭제하는 것이 정답은 아닙니다.
어떤 데이터인지, 왜 비어 있는지, 얼마나 많이 비어 있는지, 분석 목적이 무엇인지에 따라 판단이 달라질 수 있습니다.

따라서 현재 단계에서는

문제가 있다.

까지만 확인합니다.

실제 데이터 정리는 #38에서 진행합니다.

 


그렇다면 다음에는 무엇을 해야 할까?

데이터의 전체적인 상태는 확인했습니다.

하지만 아직 이런 질문에는 답하지 못합니다.

AI 과정을 수강하는 학생만 보고 싶다면?

출석률이 90% 이상인 학생만 찾으려면?

study_hours와 passed만 가져오려면?

 

현재 DataFrame에는 82개의 Row와 9개의 Column이 있습니다.
분석할 때 항상 전체 데이터가 필요한 것은 아닙니다.
우리가 원하는 데이터만 골라낼 수 있어야 합니다.
이것이 다음 단계입니다.

 


이번 글에서 해결한 질문

이번 글의 질문은 다음이었습니다.

CSV를 불러온 뒤 가장 먼저 무엇을 해야 할까?

답은 단순합니다.

분석하기 전에 데이터의 상태부터 확인해야 합니다.

Pandas에서는

pd.read_csv()

를 이용해 CSV 파일을 DataFrame으로 가져올 수 있습니다.

그리고 다음과 같은 도구를 사용했습니다.

df.head()
df.shape
df.columns
df.dtypes
df.info()

각각의 역할은 다릅니다.

기능 확인하는 것
read_csv() CSV 불러오기
head() 데이터 앞부분
shape 행과 열의 개수
columns Column 이름
dtypes Column별 자료형
info() 전체 구조·Non-Null·dtype

하지만 이번 글에서 가장 중요한 것은 함수 자체가 아닙니다.

데이터를 받는다
↓
바로 분석하지 않는다
↓
먼저 구조를 확인한다
↓
이상한 점을 찾는다
↓
그다음 분석한다

이 흐름을 기억하는 것이 훨씬 중요합니다.

 


다음 글 예고

이제 데이터가 어떻게 생겼는지는 확인했습니다.

다음에는 82개의 Row와 9개의 Column 중에서 우리가 원하는 데이터만 선택해보겠습니다.

예를 들어

study_hours Column만 선택하기

age와 passed만 선택하기

특정 Row 선택하기

AI 과정 학생만 찾기

출석률이 90% 이상인 학생만 찾기

같은 작업입니다.

 

이 과정에서 Pandas의 중요한 데이터 선택 방법인

df["column"]
df.loc[]
df.iloc[]
그리고 조건 필터링(Boolean Filtering)을 만나게 됩니다.

NumPy에서 배웠던 Indexing과 Slicing이 Pandas에서는 어떻게 달라지는지도 함께 비교해보겠습니다.

다음 질문은 이것입니다.

82명의 데이터 중 내가 원하는 행과 열만 어떻게 골라낼까?

 

 

 

 

 

728x90
반응형

'AI Journey > Pandas' 카테고리의 다른 글

Pandas 데이터 선택하기 — loc, iloc과 조건 필터링 쉽게 이해하기  (0) 2026.08.23
Pandas란 무엇일까? NumPy Array가 있는데 DataFrame이 필요한 이유  (0) 2026.08.17
'AI Journey/Pandas' 카테고리의 다른 글
  • Pandas 데이터 선택하기 — loc, iloc과 조건 필터링 쉽게 이해하기
  • Pandas란 무엇일까? NumPy Array가 있는데 DataFrame이 필요한 이유
#늑대양
#늑대양
일상과 정보, 독서의 쉼터
    반응형
  • #늑대양
    늑대양의 안식처
    #늑대양
  • 전체
    오늘
    어제
    • 분류 전체보기
      • IT
        • 네트워크
        • IT 상식
        • Python
        • 혼자 공부하는 머신러닝+딥러닝
        • 데싸노트의 실전에서 통하는 머신러닝
        • Tistory
        • IT - 생활코딩
        • WEB1 - HTML & Internet
      • AI Journey
        • Python
        • NumPy
        • Pandas
      • AI 교육과정
        • [부트캠프] 데이터 사이언티스트 과정
      • AWS
        • AWS KRUG
        • Study
        • AWS Solutions Architect
      • Terraform
        • Terraform Associate Study
      • k8s
        • CloudNet@
      • Conference
        • FinOps
        • K-디지털 서포터즈
      • NAVER CLOUD PLATFORM
        • MASTER
        • NCUC
        • 서비스 탐구생활
        • 자격증 탐구생활
      • Daily Life
      • Book
      • Study
        • 가짜연구소: Data Scientist - Pyt..
        • 가짜연구소: DE4E
      • Hobby
        • Talk
        • Movie
  • 블로그 메뉴

    • IT
    • AI 교육과정
    • AI Journey
    • Network
    • AWS
    • k8s
    • Conference
    • Book
    • Hobby
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    테라폼
    네트워크
    CloudNet@
    머신러닝
    Terraform
    dl
    딥러닝
    Numpy
    스터디
    Ai
    MGS
    AWS
    Python
    AIJourney
    파이썬
    데이터 사이언티스트
    ML
    가짜연구소
    devops
    프로젝트
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
#늑대양
Pandas CSV 불러오기 — 데이터를 받으면 가장 먼저 확인해야 할 것들
상단으로

티스토리툴바