Series 란?

Pandas의 Series는 1차원 데이터 구조로, 하나의 값 배열에 인덱스(라벨)가 결합된 형태입니다. 엑셀의 한 열(column)이나, 파이썬 리스트에 이름표를 붙여둔 구조로 생각하면 이해하기 쉽습니다. Series는 값과 인덱스를 함께 관리하기 때문에, 단순한 순서 기반 연산이 아니라 라벨 기준 연산과 자동 정렬(alignment) 이 가능하다는 점이 가장 큰 특징입니다. 이 글에서는 Series를 처음 접하는 사람도 흐름대로 이해할 수 있도록, 생성 → 속성 → 조회 → 연산 → 내장 함수 활용 순서로 정리합니다.

1. Series 객체란?

Series는 내부적으로 values, index, name, dtype 같은 요소를 함께 가지고 있습니다. values는 실제 데이터가 저장되는 영역이고, index는 각 데이터에 대응되는 라벨 역할을 합니다. name은 Series 전체를 대표하는 이름으로 선택적으로 사용할 수 있으며, dtype은 데이터의 자료형을 나타냅니다. 이러한 구조 덕분에 Series는 단순한 배열이 아니라, 라벨을 기반으로 연산과 정렬이 가능한 1차원 데이터 구조라고 볼 수 있습니다.

2. Series의 개요

가장 단순한 형태의 Series를 생성해보면 다음과 같습니다.

import pandas as pd

s = pd.Series([10, 20, 30])
print(s)

이 예제에서는 리스트를 전달해 Series를 생성했습니다. Pandas는 자동으로 0, 1, 2와 같은 정수 인덱스를 부여하며, 각 값과 인덱스를 세로 형태로 출력합니다. 마지막 줄에는 Series 전체의 데이터 타입이 표시됩니다.

인덱스를 직접 문자열로 지정할 수도 있습니다.

s = pd.Series([10, 20, 30], index=["a", "b", "c"])
print(s)

이 경우 각 값은 숫자 위치가 아니라 문자열 라벨과 연결되며, 이후에는 s[“b”]처럼 라벨 기반 접근이 가능합니다.

3. 파이썬 객체에서 Series 생성

3.1. 리스트(list)로 생성

리스트는 Series를 생성할 때 가장 자주 사용하는 입력 형태입니다.

import pandas as pd

s = pd.Series([1, 2, 3, 4])
print(s)

기본적으로는 0부터 시작하는 정수 인덱스가 자동으로 붙습니다. 인덱스와 이름을 함께 지정하면 Series의 의미를 더 명확히 표현할 수 있습니다.

s = pd.Series([1, 2, 3, 4], index=["Q1", "Q2", "Q3", "Q4"], name="sales")
print(s)

이 예제에서는 분기별 매출처럼 해석할 수 있는 Series가 만들어집니다.

3.2. 튜플(tuple)로 생성

튜플을 사용해도 리스트와 동일한 방식으로 Series가 생성됩니다.

s = pd.Series((100, 200, 300))
print(s)

튜플은 불변(immutable)이지만, Series 생성 이후의 동작에는 리스트와 차이가 없습니다.

3.3. 딕셔너리(dict)로 생성

딕셔너리로 Series를 생성하면 키는 인덱스, 값은 데이터로 사용됩니다.

s = pd.Series({"apple": 3, "banana": 5, "orange": 2})
print(s)

이 방식은 이미 의미 있는 키-값 구조를 데이터로 가지고 있을 때 특히 유용합니다.

인덱스를 따로 지정하면, 해당 인덱스 기준으로 재정렬되며 딕셔너리에 없는 키는 결측치(NaN)로 채워집니다.

s = pd.Series({"apple": 3, "banana": 5, "orange": 2}, index=["banana", "apple", "grape"])
print(s)

이처럼 결측치가 포함되면, 정수형을 유지할 수 없어 dtype이 float로 변경되는 경우가 많습니다.

3-4) 스칼라(scalar)로 생성

단일 값과 여러 개의 인덱스를 함께 전달하면, 동일한 값이 모든 인덱스에 반복되어 채워집니다.

s = pd.Series(0, index=["a", "b", "c", "d"])
print(s)

초기값을 일괄 세팅할 때 자주 사용하는 패턴입니다.

3.5. NumPy 배열(ndarray)로 생성

NumPy 배열 역시 Series의 입력으로 사용할 수 있습니다.

import numpy as np
import pandas as pd

arr = np.array([1.5, 2.5, 3.5])
s = pd.Series(arr, index=["x", "y", "z"])
print(s)

이 경우에도 배열의 값은 그대로 유지되며, 인덱스를 통해 의미를 부여할 수 있습니다.

4. Series의 속성(Attributes)

4.1. index, values, dtype

Series가 가지고 있는 기본적인 구성 요소는 속성으로 확인할 수 있습니다.

import pandas as pd

s = pd.Series([10, 20, 30], index=["a", "b", "c"], name="score")

print("index:", s.index)
print("values:", s.values)
print("dtype:", s.dtype)
  • index는 Pandas의 Index 객체
  • values는 보통 NumPy 배열 형태
  • dtype은 데이터의 자료형을 나타냅니다

4.2. name, shape, size, ndim

Series 자체의 메타 정보를 확인할 때 사용하는 속성들입니다.

print("name:", s.name)
print("shape:", s.shape)
print("size:", s.size)
print("ndim:", s.ndim)

Series는 항상 1차원이므로 ndim은 보통 1입니다.

4.3. describe()

수치형 Series에 대해 기본적인 통계 요약을 한 번에 확인할 수 있습니다.

s = pd.Series([10, 20, 30, 40])
print(s.describe())

개수, 평균, 표준편차, 최소/최대값 등이 자동으로 계산됩니다.

4.4. 결측치 확인

결측치는 데이터 분석에서 매우 중요한 요소입니다.

s = pd.Series([1, None, 3])
print(s.isna())
print(s.notna())

각 위치가 결측치인지 여부를 Boolean 값으로 반환합니다.

5. 첫 번째 행과 마지막 행 검색

5.1. head(), tail()

Series의 앞부분이나 뒷부분을 빠르게 확인할 때 사용합니다.

import pandas as pd

s = pd.Series(range(1, 11))

print(s.head())
print(s.head(3))
print(s.tail(3))

데이터 크기가 큰 경우 구조를 파악하는 데 매우 유용합니다.

5.2. 단일 값 조회: iloc, loc

s = pd.Series([100, 200, 300], index=["a", "b", "c"])

print(s.iloc[0])
print(s.loc["a"])

iloc은 위치 기준, loc은 라벨 기준 접근이라는 차이를 명확히 구분하는 것이 중요합니다.

6. 수학 연산

6.1. 스칼라 연산

import pandas as pd

s = pd.Series([1, 2, 3])

print(s + 10)
print(s * 2)
print(s ** 2)

각 연산은 Series 전체에 벡터화되어 적용됩니다.

6.2. Series 간 연산과 인덱스 정렬

import pandas as pd

a = pd.Series([10, 20, 30], index=["x", "y", "z"])
b = pd.Series([1, 2, 3], index=["y", "z", "w"])

print(a + b)

연산 시 인덱스를 기준으로 자동 정렬되며, 한쪽에만 존재하는 인덱스는 결측치로 처리됩니다.

6.3.결측치 보정 연산

print(a.add(b, fill_value=0))

존재하지 않는 값을 0으로 간주해 연산하고 싶을 때 사용하는 방식입니다.

6.4. 집계 함수

s = pd.Series([10, 20, 30, 40])

print("sum:", s.sum())
print("mean:", s.mean())
print("min:", s.min())
print("max:", s.max())
print("std:", s.std())
print("var:", s.var())

데이터 분석에서 가장 자주 쓰이는 기본 통계 연산들입니다.

6.5. 조건 기반 처리

s = pd.Series([5, 10, 15, 20])

print(s[s >= 10])
print(s.where(s >= 10))
print(s.where(s >= 10, 0))

조건에 따라 값을 필터링하거나 대체할 수 있습니다.

6.6. 값 변환

s = pd.Series(["10", "20", "30"])

s2 = s.astype(int)
print(s2)

grade = pd.Series([90, 70, 85], index=["A", "B", "C"])
print(grade.map(lambda x: "pass" if x >= 80 else "fail"))

타입 변환이나 값 매핑은 전처리 단계에서 매우 자주 사용됩니다.

7. Series와 파이썬 내장 함수

7.1. len()

import pandas as pd

s = pd.Series([1, 2, 3, 4])
print(len(s))

Series의 길이를 반환합니다.

7.2. sum(), min(), max()

print(sum(s))
print(min(s))
print(max(s))

가능은 하지만, 실무에서는 Pandas 메서드 사용이 더 명확합니다.

7.3. sorted()

s = pd.Series([3, 1, 2], index=["c", "a", "b"])

print(sorted(s))

값만 정렬된 리스트가 반환되며 인덱스 정보는 사라집니다.

print(s.sort_values())
print(s.sort_index())

Series 구조를 유지하려면 Pandas 메서드를 사용합니다.

7.4. list(), set()

s = pd.Series([1, 2, 2, 3])

print(list(s))
print(set(s))

Series를 일반 파이썬 컬렉션으로 변환할 수 있습니다.

7.5. any(), all()

s = pd.Series([True, True, False])

print(any(s))
print(all(s))

Boolean 조건을 요약할 때 사용하며, Pandas 메서드 버전도 자주 활용됩니다.

Series는 Pandas의 모든 데이터 구조의 출발점입니다. Series의 인덱스 개념과 연산 규칙을 정확히 이해하면, 이후 DataFrame 조작도 자연스럽게 이어집니다.