[Python] Pandas의 배열 참조 방법

Pandas를 배우기 전까지…

나는 데이터를 다룰 때 항상 하나씩 직접 보면서 처리하는방식에 익숙했다.
그게 디버깅을 실시간으로 하며, 정확한 코드를 짜는거라고 생각을 했으니까..

또한 내가 주로 사용했던 SQL과 JAVA에서는 배열이든 리스트든, 인덱스는 언제나 숫자였고, 그 숫자는 곧 위치를 의미했다. 특정 값을 찾고 싶다면 반복을 돌리거나 조건을 걸어 하나씩 비교하는 게 당연한 흐름이었다.

하지만 Pandas의 데이터 프레임은 처음부터 다른 접근을 요구했다.
인덱스를 라벨이라고 칭하며, 인덱싱과 슬라이싱에도
df[1:3], df.loc[1:3], df.iloc[1:3] 라는 새로운 문법들이 등장했다.


불리언 인덱싱은 그나마 감이 온다

그 와중에 좀 적응이 된 내용은 불리언 인덱싱이다.
조건을 주고, 그 조건에 맞는 행만 추려내는 방식은 마치 SQL의 WHERE절처럼 느껴진다.

df[df['score'] > 85]

이 한 줄이 말하고자 하는 의도는 명확하다.
score가 85보다 큰 행들만 골라내라.

Pandas가 내부에서 [False, True, True] 같은 불리언 배열을 만들어 필터링한다는 걸 알고 나면,
구조도 어느 정도 납득이 간다.

다만, 여기서도 .loc을 함께 쓰는 것이 더 안전하다는 말을 듣고 나면 또 고민이 생긴다.
“왜 .loc을 붙여야 하지?”, “df[조건]만으로는 부족한가?” 같은 의문이 연달아 따라온다.


loc는 왜 이렇게 생겨먹었나..

.loc은 겉보기에 그냥 슬라이싱 문법처럼 생겼다.
df.loc[10:11] 같은 코드를 보면, 딱히 낯설 게 없어 보인다.

그런데 실제로 써보면, 이건 단순한 슬라이싱이 아니다.
loc는 어떤 값을 ‘찾는 방식 자체’가 다르다.

일반적인 인덱싱은 순서대로 값을 자른다.
슬라이싱이면 앞에서부터 몇 번째, 몇 번째까지 자른다는 흐름이 명확하다.

그런데 .loc그게 아니다.

df.loc[df['score'] > 85].loc[11]

여기서 무슨 일이 일어나는가..?

  1. 첫 번째 .loc[df['score'] > 85]에서 조건을 만족하는 행 전체를 필터링한다.
  2. 그 결과가 새로운 DataFrame이 된다.
  3. 그 위에서 다시 .loc[11]을 하면, 그 결과 내부의 인덱스 라벨 11을 탐색하게 된다.

한 줄짜리지만 실제로는 불리언 인덱싱 → 결과 슬라이싱 → 하위 추출이라는

세 단계가 압축돼 있는 셈이다.

이게 .loc이 헷갈리는 진짜 이유였다.
탐색 흐름이 연속적이지 않고, 중간 결과에 따라 탐색 기준이 달라지며,
그 와중에도 문법은 너무 간단하게 생겨서 실수하기 쉽다.

숫자라서 헷갈린 게 아니다.
탐색 자체가, 사고 흐름 자체가 낯설었던 거다.


마무리..

numpy와도 마찬가지로, 내가 헷갈렸던 건 문법 그 자체보다도 사고 방식의 차이였다.

그 추상화가 처음엔 낯설고 불편했지만,
하나씩 해석해보며 익숙해지다 보니 왜 이렇게 만들었는지도 조금씩 이해가 되기 시작했다.

내가 익숙하지 않았던 건 문법이 아니라, 그 수단을 받아들이는 사고의 전환이었을지도 모른다.

Categories:

Updated:

Leave a comment