{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "**도구 - 판다스(pandas)**\n", "\n", "*`pandas` 라이브러리는 사용하기 쉬운 고성능 데이터 구조와 데이터 분석 도구를 제공합니다. 주 데이터 구조는 `DataFrame`입니다. 이를 인-메모리(in-memory) 2D 테이블로 생각할 수 있습니다(열 이름과 행 레이블이 있는 스프레드시트와 비슷합니다). 엑셀에 있는 많은 기능을 프로그램에서 사용할 수 있습니다. 여기에는 피봇 테이블이나 다른 열을 기반으로 열을 계산하고 그래프 출력하는 기능 등이 포함됩니다. 열 값으로 행을 그룹핑할 수도 있습니다. 또한 SQL과 비슷하게 테이블을 조인할 수 있습니다. 판다스는 시계열 데이터를 다루는데도 뛰어납니다.*\n", "\n", "필요 라이브러리:\n", "\n", "* 넘파이(NumPy) – 넘파이에 익숙하지 않다면 지금 [넘파이 튜토리얼](tools_numpy.ipynb)을 둘러 보세요." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", " \n", "
\n", " 구글 코랩에서 실행하기\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 설정" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "먼저 `pandas`를 임포트합니다. 보통 `pd`로 임포트합니다:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:24.221923Z", "iopub.status.busy": "2020-10-16T07:31:24.220070Z", "iopub.status.idle": "2020-10-16T07:31:24.555259Z", "shell.execute_reply": "2020-10-16T07:31:24.556630Z" } }, "outputs": [], "source": [ "import pandas as pd" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# `Series` 객체\n", "\n", "`pandas` 라이브러리는 다음과 같은 유용한 데이터 구조를 포함하고 있습니다:\n", "\n", "* `Series` 객체를 곧 이어서 설명하겠습니다. `Series` 객체는 1D 배열입니다. (열 이름과 행 레이블을 가진) 스프레드시트의 열과 비슷합니다.\n", "* `DataFrame` 객체는 2D 테이블입니다. (열 이름과 행 레이블을 가진) 스프레드시트와 비슷합니다." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## `Series` 만들기\n", "\n", "첫 번째 `Series` 객체를 만들어 보죠!" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:24.570090Z", "iopub.status.busy": "2020-10-16T07:31:24.568601Z", "iopub.status.idle": "2020-10-16T07:31:24.577334Z", "shell.execute_reply": "2020-10-16T07:31:24.578463Z" } }, "outputs": [ { "data": { "text/plain": [ "0 2\n", "1 -1\n", "2 3\n", "3 5\n", "dtype: int64" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s = pd.Series([2,-1,3,5])\n", "s" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1D `ndarray`와 비슷합니다\n", "\n", "`Series` 객체는 넘파이 `ndarray`와 비슷하게 동작합니다. 넘파이 함수에 매개변수로 종종 전달할 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:24.588613Z", "iopub.status.busy": "2020-10-16T07:31:24.587550Z", "iopub.status.idle": "2020-10-16T07:31:24.592275Z", "shell.execute_reply": "2020-10-16T07:31:24.593060Z" } }, "outputs": [ { "data": { "text/plain": [ "0 7.389056\n", "1 0.367879\n", "2 20.085537\n", "3 148.413159\n", "dtype: float64" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import numpy as np\n", "np.exp(s)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`Series` 객체에 대한 산술 연산도 가능합니다. `ndarray`와 비슷하게 *원소별*로 적용됩니다:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:24.600732Z", "iopub.status.busy": "2020-10-16T07:31:24.599483Z", "iopub.status.idle": "2020-10-16T07:31:24.613392Z", "shell.execute_reply": "2020-10-16T07:31:24.614382Z" } }, "outputs": [ { "data": { "text/plain": [ "0 1002\n", "1 1999\n", "2 3003\n", "3 4005\n", "dtype: int64" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s + [1000,2000,3000,4000]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "넘파이와 비슷하게 `Series`에 하나의 숫자를 더하면 `Series`에 있는 모든 원소에 더해집니다. 이를 *브로드캐스팅*(broadcasting)이라고 합니다:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:24.623100Z", "iopub.status.busy": "2020-10-16T07:31:24.621859Z", "iopub.status.idle": "2020-10-16T07:31:24.626335Z", "shell.execute_reply": "2020-10-16T07:31:24.627258Z" } }, "outputs": [ { "data": { "text/plain": [ "0 1002\n", "1 999\n", "2 1003\n", "3 1005\n", "dtype: int64" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s + 1000" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`*`나 `/` 같은 모든 이항 연산과 심지어 조건 연산에서도 마찬가지입니다:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:24.636724Z", "iopub.status.busy": "2020-10-16T07:31:24.635629Z", "iopub.status.idle": "2020-10-16T07:31:24.640020Z", "shell.execute_reply": "2020-10-16T07:31:24.641002Z" } }, "outputs": [ { "data": { "text/plain": [ "0 False\n", "1 True\n", "2 False\n", "3 False\n", "dtype: bool" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s < 0" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 인덱스 레이블\n", "\n", "`Series` 객체에 있는 각 원소는 *인덱스 레이블*(index label)이라 불리는 고유한 식별자를 가지고 있습니다. 기본적으로 `Series`에 있는 원소의 순서입니다(`0`에서 시작합니다). 하지만 수동으로 인덱스 레이블을 지정할 수도 있습니다:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:24.652237Z", "iopub.status.busy": "2020-10-16T07:31:24.651072Z", "iopub.status.idle": "2020-10-16T07:31:24.655568Z", "shell.execute_reply": "2020-10-16T07:31:24.656530Z" } }, "outputs": [ { "data": { "text/plain": [ "alice 68\n", "bob 83\n", "charles 112\n", "darwin 68\n", "dtype: int64" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s2 = pd.Series([68, 83, 112, 68], index=[\"alice\", \"bob\", \"charles\", \"darwin\"])\n", "s2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "그다음 `dict`처럼 `Series`를 사용할 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:24.664537Z", "iopub.status.busy": "2020-10-16T07:31:24.663371Z", "iopub.status.idle": "2020-10-16T07:31:24.667750Z", "shell.execute_reply": "2020-10-16T07:31:24.668655Z" } }, "outputs": [ { "data": { "text/plain": [ "83" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s2[\"bob\"]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "일반 배열처럼 정수 인덱스를 사용하여 계속 원소에 접근할 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:24.676616Z", "iopub.status.busy": "2020-10-16T07:31:24.675524Z", "iopub.status.idle": "2020-10-16T07:31:24.680902Z", "shell.execute_reply": "2020-10-16T07:31:24.679919Z" } }, "outputs": [ { "data": { "text/plain": [ "83" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s2[1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "레이블이나 정수를 사용해 접근할 때 명확하게 하기 위해 레이블은 `loc` 속성을 사용하고 정수는 `iloc` 속성을 사용하는 것이 좋습니다:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:24.688670Z", "iopub.status.busy": "2020-10-16T07:31:24.687572Z", "iopub.status.idle": "2020-10-16T07:31:24.691843Z", "shell.execute_reply": "2020-10-16T07:31:24.692745Z" } }, "outputs": [ { "data": { "text/plain": [ "83" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s2.loc[\"bob\"]" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:24.700414Z", "iopub.status.busy": "2020-10-16T07:31:24.699308Z", "iopub.status.idle": "2020-10-16T07:31:24.704534Z", "shell.execute_reply": "2020-10-16T07:31:24.703582Z" } }, "outputs": [ { "data": { "text/plain": [ "83" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s2.iloc[1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`Series`는 인덱스 레이블을 슬라이싱할 수도 있습니다:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:24.713637Z", "iopub.status.busy": "2020-10-16T07:31:24.712448Z", "iopub.status.idle": "2020-10-16T07:31:24.717062Z", "shell.execute_reply": "2020-10-16T07:31:24.718032Z" } }, "outputs": [ { "data": { "text/plain": [ "bob 83\n", "charles 112\n", "dtype: int64" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s2.iloc[1:3]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "기본 정수 레이블을 사용할 때 예상 외의 결과를 만들 수 있기 때문에 주의해야 합니다:" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:24.727693Z", "iopub.status.busy": "2020-10-16T07:31:24.726532Z", "iopub.status.idle": "2020-10-16T07:31:24.731715Z", "shell.execute_reply": "2020-10-16T07:31:24.730767Z" } }, "outputs": [ { "data": { "text/plain": [ "0 1000\n", "1 1001\n", "2 1002\n", "3 1003\n", "dtype: int64" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "surprise = pd.Series([1000, 1001, 1002, 1003])\n", "surprise" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:24.743690Z", "iopub.status.busy": "2020-10-16T07:31:24.742592Z", "iopub.status.idle": "2020-10-16T07:31:24.747552Z", "shell.execute_reply": "2020-10-16T07:31:24.748475Z" } }, "outputs": [ { "data": { "text/plain": [ "2 1002\n", "3 1003\n", "dtype: int64" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "surprise_slice = surprise[2:]\n", "surprise_slice" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "보세요. 첫 번째 원소의 인덱스 레이블이 `2`입니다. 따라서 슬라이싱 결과에서 인덱스 레이블 `0`인 원소는 없습니다:" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:24.756602Z", "iopub.status.busy": "2020-10-16T07:31:24.755419Z", "iopub.status.idle": "2020-10-16T07:31:24.759801Z", "shell.execute_reply": "2020-10-16T07:31:24.760708Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "키 에러: 0\n" ] } ], "source": [ "try:\n", " surprise_slice[0]\n", "except KeyError as e:\n", " print(\"키 에러:\", e)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "하지만 `iloc` 속성을 사용해 정수 인덱스로 원소에 접근할 수 있습니다. `Series` 객체를 사용할 때 `loc`와 `iloc`를 사용하는 것이 좋은 이유입니다:" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:24.768724Z", "iopub.status.busy": "2020-10-16T07:31:24.767621Z", "iopub.status.idle": "2020-10-16T07:31:24.772216Z", "shell.execute_reply": "2020-10-16T07:31:24.773102Z" } }, "outputs": [ { "data": { "text/plain": [ "1002" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "surprise_slice.iloc[0]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## `dict`에서 초기화\n", "\n", "`dict`에서 `Series` 객체를 만들 수 있습니다. 키는 인덱스 레이블로 사용됩니다:" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:24.787621Z", "iopub.status.busy": "2020-10-16T07:31:24.786507Z", "iopub.status.idle": "2020-10-16T07:31:24.792357Z", "shell.execute_reply": "2020-10-16T07:31:24.791273Z" } }, "outputs": [ { "data": { "text/plain": [ "alice 68\n", "bob 83\n", "colin 86\n", "darwin 68\n", "dtype: int64" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "weights = {\"alice\": 68, \"bob\": 83, \"colin\": 86, \"darwin\": 68}\n", "s3 = pd.Series(weights)\n", "s3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`Series`에 포함할 원소를 제어하고 `index`를 지정하여 명시적으로 순서를 결정할 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:24.802869Z", "iopub.status.busy": "2020-10-16T07:31:24.801619Z", "iopub.status.idle": "2020-10-16T07:31:24.805950Z", "shell.execute_reply": "2020-10-16T07:31:24.806812Z" } }, "outputs": [ { "data": { "text/plain": [ "colin 86\n", "alice 68\n", "dtype: int64" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s4 = pd.Series(weights, index = [\"colin\", \"alice\"])\n", "s4" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 자동 정렬\n", "\n", "여러 개의 `Series` 객체를 다룰 때 `pandas`는 자동으로 인덱스 레이블에 따라 원소를 정렬합니다." ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:24.819432Z", "iopub.status.busy": "2020-10-16T07:31:24.818333Z", "iopub.status.idle": "2020-10-16T07:31:24.824399Z", "shell.execute_reply": "2020-10-16T07:31:24.825448Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Index(['alice', 'bob', 'charles', 'darwin'], dtype='object')\n", "Index(['alice', 'bob', 'colin', 'darwin'], dtype='object')\n" ] }, { "data": { "text/plain": [ "alice 136.0\n", "bob 166.0\n", "charles NaN\n", "colin NaN\n", "darwin 136.0\n", "dtype: float64" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print(s2.keys())\n", "print(s3.keys())\n", "\n", "s2 + s3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "만들어진 `Series`는 `s2`와 `s3`의 인덱스 레이블의 합집합을 담고 있습니다. `s2`에 `\"colin\"`이 없고 `s3`에 `\"charles\"`가 없기 때문에 이 원소는 `NaN` 값을 가집니다(Not-a-Number는 *누락*이란 의미입니다).\n", "\n", "자동 정렬은 구조가 다고 누락된 값이 있는 여러 데이터를 다룰 때 매우 편리합니다. 하지만 올바른 인덱스 레이블을 지정하는 것을 잊는다면 원치않는 결과를 얻을 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:24.839789Z", "iopub.status.busy": "2020-10-16T07:31:24.838536Z", "iopub.status.idle": "2020-10-16T07:31:24.845810Z", "shell.execute_reply": "2020-10-16T07:31:24.846735Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "s2 = [ 68 83 112 68]\n", "s5 = [1000 1000 1000 1000]\n" ] }, { "data": { "text/plain": [ "alice NaN\n", "bob NaN\n", "charles NaN\n", "darwin NaN\n", "0 NaN\n", "1 NaN\n", "2 NaN\n", "3 NaN\n", "dtype: float64" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s5 = pd.Series([1000,1000,1000,1000])\n", "print(\"s2 =\", s2.values)\n", "print(\"s5 =\", s5.values)\n", "\n", "s2 + s5" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "레이블이 하나도 맞지 않기 때문에 판다스가 이 `Series`를 정렬할 수 없습니다. 따라서 모두 `NaN`이 되었습니다." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 스칼라로 초기화\n", "\n", "스칼라와 인덱스 레이블의 리스트로 `Series` 객체를 초기화할 수도 있습니다: 모든 원소가 이 스칼라 값으로 설정됩니다." ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:24.857808Z", "iopub.status.busy": "2020-10-16T07:31:24.856592Z", "iopub.status.idle": "2020-10-16T07:31:24.861265Z", "shell.execute_reply": "2020-10-16T07:31:24.862233Z" } }, "outputs": [ { "data": { "text/plain": [ "life 42\n", "universe 42\n", "everything 42\n", "dtype: int64" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "meaning = pd.Series(42, [\"life\", \"universe\", \"everything\"])\n", "meaning" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## `Series` 이름\n", "\n", "`Series`는 `name`을 가질 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:24.874388Z", "iopub.status.busy": "2020-10-16T07:31:24.873208Z", "iopub.status.idle": "2020-10-16T07:31:24.878224Z", "shell.execute_reply": "2020-10-16T07:31:24.879152Z" } }, "outputs": [ { "data": { "text/plain": [ "bob 83\n", "alice 68\n", "Name: weights, dtype: int64" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s6 = pd.Series([83, 68], index=[\"bob\", \"alice\"], name=\"weights\")\n", "s6" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## `Series` 그래프 출력\n", "\n", "맷플롯립을 사용해 `Series` 데이터를 쉽게 그래프로 출력할 수 있습니다(맷플롯립에 대한 자세한 설명은 [맷플롯립 튜토리얼](tools_matplotlib.ipynb)을 참고하세요). 맷플롯립을 임포트하고 `plot()` 메서드를 호출하면 끝입니다:" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:24.893980Z", "iopub.status.busy": "2020-10-16T07:31:24.892680Z", "iopub.status.idle": "2020-10-16T07:31:25.181629Z", "shell.execute_reply": "2020-10-16T07:31:25.183074Z" }, "scrolled": true }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "%matplotlib inline\n", "import matplotlib.pyplot as plt\n", "temperatures = [4.4,5.1,6.1,6.2,6.1,6.1,5.7,5.2,4.7,4.1,3.9,3.5]\n", "s7 = pd.Series(temperatures, name=\"Temperature\")\n", "s7.plot()\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "데이터를 그래프로 출력하는데 많은 *옵션*이 있습니다. 여기에서 모두 나열할 필요는 없습니다. 특정 종류의 그래프(히스토그램, 파이 차트 등)가 필요하면 판다스 문서의 [시각화](http://pandas.pydata.org/pandas-docs/stable/visualization.html) 섹션에서 예제 코드를 참고하세요." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 시간 다루기\n", "\n", "많은 데이터셋에 타임스탬프가 포함되어 있습니다. 판다스는 이런 데이터를 다루는데 뛰어납니다:\n", "* (2016Q3 같은) 기간과 (\"monthly\" 같은) 빈도를 표현할 수 있습니다.\n", "* 기간을 실제 타임스탬프로 변환하거나 그 반대로 변환할 수 있습니다.\n", "* 데이터를 리샘플링하고 원하는 방식으로 값을 모을 수 있습니다.\n", "* 시간대를 다룰 수 있습니다.\n", "\n", "## 시간 범위\n", "\n", "먼저 `pd.date_range()`를 사용해 시계열을 만들어 보죠. 이 함수는 2016년 10월 29일 5:30pm에서 시작하여 12시간마다 하나의 datetime을 담고 있는 `DatetimeIndex`를 반환합니다." ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:25.201288Z", "iopub.status.busy": "2020-10-16T07:31:25.199933Z", "iopub.status.idle": "2020-10-16T07:31:25.204600Z", "shell.execute_reply": "2020-10-16T07:31:25.205726Z" } }, "outputs": [ { "data": { "text/plain": [ "DatetimeIndex(['2016-10-29 17:30:00', '2016-10-29 18:30:00',\n", " '2016-10-29 19:30:00', '2016-10-29 20:30:00',\n", " '2016-10-29 21:30:00', '2016-10-29 22:30:00',\n", " '2016-10-29 23:30:00', '2016-10-30 00:30:00',\n", " '2016-10-30 01:30:00', '2016-10-30 02:30:00',\n", " '2016-10-30 03:30:00', '2016-10-30 04:30:00'],\n", " dtype='datetime64[ns]', freq='H')" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dates = pd.date_range('2016/10/29 5:30pm', periods=12, freq='H')\n", "dates" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "이 `DatetimeIndex`를 `Series`의 인덱스로 사용할수 있습니다:" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:25.217308Z", "iopub.status.busy": "2020-10-16T07:31:25.215973Z", "iopub.status.idle": "2020-10-16T07:31:25.220460Z", "shell.execute_reply": "2020-10-16T07:31:25.221384Z" } }, "outputs": [ { "data": { "text/plain": [ "2016-10-29 17:30:00 4.4\n", "2016-10-29 18:30:00 5.1\n", "2016-10-29 19:30:00 6.1\n", "2016-10-29 20:30:00 6.2\n", "2016-10-29 21:30:00 6.1\n", "2016-10-29 22:30:00 6.1\n", "2016-10-29 23:30:00 5.7\n", "2016-10-30 00:30:00 5.2\n", "2016-10-30 01:30:00 4.7\n", "2016-10-30 02:30:00 4.1\n", "2016-10-30 03:30:00 3.9\n", "2016-10-30 04:30:00 3.5\n", "Freq: H, dtype: float64" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "temp_series = pd.Series(temperatures, dates)\n", "temp_series" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "이 시리즈를 그래프로 출력해 보죠:" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:25.250697Z", "iopub.status.busy": "2020-10-16T07:31:25.249514Z", "iopub.status.idle": "2020-10-16T07:31:25.416215Z", "shell.execute_reply": "2020-10-16T07:31:25.417660Z" } }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "temp_series.plot(kind=\"bar\")\n", "\n", "plt.grid(True)\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 리샘플링\n", "\n", "판다스는 매우 간단하게 시계열을 리샘플링할 수 있습니다. `resample()` 메서드를 호출하고 새로운 주기를 지정하면 됩니다:" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:25.425130Z", "iopub.status.busy": "2020-10-16T07:31:25.424093Z", "iopub.status.idle": "2020-10-16T07:31:25.441445Z", "shell.execute_reply": "2020-10-16T07:31:25.440279Z" } }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "temp_series_freq_2H = temp_series.resample(\"2H\")\n", "temp_series_freq_2H" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "리샘플링 연산은 사실 지연된 연산입니다. 그래서 `Series` 객체 대신 `DatetimeIndexResampler` 객체가 반환됩니다. 실제 리샘플링 연산을 수행하려면 `mean()` 같은 메서드를 호출할 수 있습니다. 이 메서드는 연속적인 시간 쌍에 대해 평균을 계산합니다:" ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:25.448657Z", "iopub.status.busy": "2020-10-16T07:31:25.446880Z", "iopub.status.idle": "2020-10-16T07:31:25.451798Z", "shell.execute_reply": "2020-10-16T07:31:25.452607Z" } }, "outputs": [], "source": [ "temp_series_freq_2H = temp_series_freq_2H.mean()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "결과를 그래프로 출력해 보죠:" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:25.510003Z", "iopub.status.busy": "2020-10-16T07:31:25.508970Z", "iopub.status.idle": "2020-10-16T07:31:25.597932Z", "shell.execute_reply": "2020-10-16T07:31:25.599362Z" } }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "temp_series_freq_2H.plot(kind=\"bar\")\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "2시간 간격으로 어떻게 값이 수집되었는지 확인해 보세요. 예를 들어 6-8pm 간격을 보면 6:30pm에서 `5.1`이고 7:30pm에서 `6.1`입니다. 리샘플링 후에 `5.1`과 `6.1`의 평균인 `5.6` 하나를 얻었습니다. 평균말고 어떤 집계 함수(aggregation function)도 사용할 수 있습니다. 예를 들어 각 기간에서 최솟값을 찾을 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:25.607951Z", "iopub.status.busy": "2020-10-16T07:31:25.606867Z", "iopub.status.idle": "2020-10-16T07:31:25.611285Z", "shell.execute_reply": "2020-10-16T07:31:25.612183Z" } }, "outputs": [ { "data": { "text/plain": [ "2016-10-29 16:00:00 4.4\n", "2016-10-29 18:00:00 5.1\n", "2016-10-29 20:00:00 6.1\n", "2016-10-29 22:00:00 5.7\n", "2016-10-30 00:00:00 4.7\n", "2016-10-30 02:00:00 3.9\n", "2016-10-30 04:00:00 3.5\n", "Freq: 2H, dtype: float64" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "temp_series_freq_2H = temp_series.resample(\"2H\").min()\n", "temp_series_freq_2H" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "또는 동일한 효과를 내는 `apply()` 메서드를 사용할 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:25.629068Z", "iopub.status.busy": "2020-10-16T07:31:25.627935Z", "iopub.status.idle": "2020-10-16T07:31:25.632613Z", "shell.execute_reply": "2020-10-16T07:31:25.633842Z" } }, "outputs": [ { "data": { "text/plain": [ "2016-10-29 16:00:00 4.4\n", "2016-10-29 18:00:00 5.1\n", "2016-10-29 20:00:00 6.1\n", "2016-10-29 22:00:00 5.7\n", "2016-10-30 00:00:00 4.7\n", "2016-10-30 02:00:00 3.9\n", "2016-10-30 04:00:00 3.5\n", "Freq: 2H, dtype: float64" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "temp_series_freq_2H = temp_series.resample(\"2H\").apply(np.min)\n", "temp_series_freq_2H" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 업샘플링과 보간\n", "\n", "다운샘플링의 예를 보았습니다. 하지만 업샘플링(즉, 빈도를 높입니다)도 할 수 있습니다. 하지만 데이터에 구멍을 만듭니다:" ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:25.646456Z", "iopub.status.busy": "2020-10-16T07:31:25.645255Z", "iopub.status.idle": "2020-10-16T07:31:25.649342Z", "shell.execute_reply": "2020-10-16T07:31:25.650294Z" } }, "outputs": [ { "data": { "text/plain": [ "2016-10-29 17:30:00 4.4\n", "2016-10-29 17:45:00 NaN\n", "2016-10-29 18:00:00 NaN\n", "2016-10-29 18:15:00 NaN\n", "2016-10-29 18:30:00 5.1\n", "2016-10-29 18:45:00 NaN\n", "2016-10-29 19:00:00 NaN\n", "2016-10-29 19:15:00 NaN\n", "2016-10-29 19:30:00 6.1\n", "2016-10-29 19:45:00 NaN\n", "Freq: 15T, dtype: float64" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "temp_series_freq_15min = temp_series.resample(\"15Min\").mean()\n", "temp_series_freq_15min.head(n=10) # `head`는 상위 n 개의 값만 출력합니다" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "한가지 방법은 보간으로 사이를 채우는 것입니다. 이렇게 하려면 `interpolate()` 메서드를 호출합니다. 기본값은 선형 보간이지만 3차 보간(cubic interpolation) 같은 다른 방법을 선택할 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:25.661000Z", "iopub.status.busy": "2020-10-16T07:31:25.659794Z", "iopub.status.idle": "2020-10-16T07:31:25.736426Z", "shell.execute_reply": "2020-10-16T07:31:25.735488Z" }, "scrolled": true }, "outputs": [ { "data": { "text/plain": [ "2016-10-29 17:30:00 4.400000\n", "2016-10-29 17:45:00 4.452911\n", "2016-10-29 18:00:00 4.605113\n", "2016-10-29 18:15:00 4.829758\n", "2016-10-29 18:30:00 5.100000\n", "2016-10-29 18:45:00 5.388992\n", "2016-10-29 19:00:00 5.669887\n", "2016-10-29 19:15:00 5.915839\n", "2016-10-29 19:30:00 6.100000\n", "2016-10-29 19:45:00 6.203621\n", "Freq: 15T, dtype: float64" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "temp_series_freq_15min = temp_series.resample(\"15Min\").interpolate(method=\"cubic\")\n", "temp_series_freq_15min.head(n=10)" ] }, { "cell_type": "code", "execution_count": 34, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:25.766770Z", "iopub.status.busy": "2020-10-16T07:31:25.764902Z", "iopub.status.idle": "2020-10-16T07:31:25.929920Z", "shell.execute_reply": "2020-10-16T07:31:25.931211Z" } }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "temp_series.plot(label=\"Period: 1 hour\")\n", "temp_series_freq_15min.plot(label=\"Period: 15 minutes\")\n", "plt.legend()\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 시간대\n", "\n", "기본적으로 datetime은 *단순*합니다. 시간대(timezone)을 고려하지 않죠. 따라서 2016-10-30 02:30는 파리나 뉴욕이나 2016년 10월 30일 2:30pm입니다. `tz_localize()` 메서드로 시간대를 고려한 datetime을 만들 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:25.939079Z", "iopub.status.busy": "2020-10-16T07:31:25.937520Z", "iopub.status.idle": "2020-10-16T07:31:25.969458Z", "shell.execute_reply": "2020-10-16T07:31:25.970302Z" } }, "outputs": [ { "data": { "text/plain": [ "2016-10-29 17:30:00-04:00 4.4\n", "2016-10-29 18:30:00-04:00 5.1\n", "2016-10-29 19:30:00-04:00 6.1\n", "2016-10-29 20:30:00-04:00 6.2\n", "2016-10-29 21:30:00-04:00 6.1\n", "2016-10-29 22:30:00-04:00 6.1\n", "2016-10-29 23:30:00-04:00 5.7\n", "2016-10-30 00:30:00-04:00 5.2\n", "2016-10-30 01:30:00-04:00 4.7\n", "2016-10-30 02:30:00-04:00 4.1\n", "2016-10-30 03:30:00-04:00 3.9\n", "2016-10-30 04:30:00-04:00 3.5\n", "dtype: float64" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "temp_series_ny = temp_series.tz_localize(\"America/New_York\")\n", "temp_series_ny" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "모든 datetime에 `-04:00`이 추가됩니다. 즉 모든 시간은 [UTC](https://en.wikipedia.org/wiki/Coordinated_Universal_Time) - 4시간을 의미합니다.\n", "\n", "다음처럼 파리 시간대로 바꿀 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:25.975427Z", "iopub.status.busy": "2020-10-16T07:31:25.974415Z", "iopub.status.idle": "2020-10-16T07:31:25.981708Z", "shell.execute_reply": "2020-10-16T07:31:25.982510Z" } }, "outputs": [ { "data": { "text/plain": [ "2016-10-29 23:30:00+02:00 4.4\n", "2016-10-30 00:30:00+02:00 5.1\n", "2016-10-30 01:30:00+02:00 6.1\n", "2016-10-30 02:30:00+02:00 6.2\n", "2016-10-30 02:30:00+01:00 6.1\n", "2016-10-30 03:30:00+01:00 6.1\n", "2016-10-30 04:30:00+01:00 5.7\n", "2016-10-30 05:30:00+01:00 5.2\n", "2016-10-30 06:30:00+01:00 4.7\n", "2016-10-30 07:30:00+01:00 4.1\n", "2016-10-30 08:30:00+01:00 3.9\n", "2016-10-30 09:30:00+01:00 3.5\n", "dtype: float64" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "temp_series_paris = temp_series_ny.tz_convert(\"Europe/Paris\")\n", "temp_series_paris" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "UTC와의 차이가 `+02:00`에서 `+01:00`으로 바뀐 것을 알 수 있습니다. 이는 프랑스가 10월 30일 3am에 겨울 시간으로 바꾸기 때문입니다(2am으로 바뀝니다). 따라서 2:30am이 두 번 등장합니다! 시간대가 없는 표현으로 돌아가 보죠(시간대가 없이 지역 시간으로 매시간 로그를 기록하는 경우 이와 비슷할 것입니다):" ] }, { "cell_type": "code", "execution_count": 37, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:25.992461Z", "iopub.status.busy": "2020-10-16T07:31:25.991439Z", "iopub.status.idle": "2020-10-16T07:31:25.996320Z", "shell.execute_reply": "2020-10-16T07:31:25.997330Z" } }, "outputs": [ { "data": { "text/plain": [ "2016-10-29 23:30:00 4.4\n", "2016-10-30 00:30:00 5.1\n", "2016-10-30 01:30:00 6.1\n", "2016-10-30 02:30:00 6.2\n", "2016-10-30 02:30:00 6.1\n", "2016-10-30 03:30:00 6.1\n", "2016-10-30 04:30:00 5.7\n", "2016-10-30 05:30:00 5.2\n", "2016-10-30 06:30:00 4.7\n", "2016-10-30 07:30:00 4.1\n", "2016-10-30 08:30:00 3.9\n", "2016-10-30 09:30:00 3.5\n", "dtype: float64" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "temp_series_paris_naive = temp_series_paris.tz_localize(None)\n", "temp_series_paris_naive" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "이렇게 되면 `02:30`이 정말 애매합니다. 시간대가 없는 datetime을 파리 시간대로 바꿀 때 에러가 발생합니다:" ] }, { "cell_type": "code", "execution_count": 38, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.006045Z", "iopub.status.busy": "2020-10-16T07:31:26.004859Z", "iopub.status.idle": "2020-10-16T07:31:26.009183Z", "shell.execute_reply": "2020-10-16T07:31:26.010136Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Cannot infer dst time from 2016-10-30 02:30:00, try using the 'ambiguous' argument\n" ] } ], "source": [ "try:\n", " temp_series_paris_naive.tz_localize(\"Europe/Paris\")\n", "except Exception as e:\n", " print(type(e))\n", " print(e)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "다행히 `ambiguous` 매개변수를 사용하면 판다스가 타임스탬프의 순서를 기반으로 적절한 DST(일광 절약 시간제)를 추측합니다:" ] }, { "cell_type": "code", "execution_count": 39, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.021302Z", "iopub.status.busy": "2020-10-16T07:31:26.020109Z", "iopub.status.idle": "2020-10-16T07:31:26.024328Z", "shell.execute_reply": "2020-10-16T07:31:26.025304Z" } }, "outputs": [ { "data": { "text/plain": [ "2016-10-29 23:30:00+02:00 4.4\n", "2016-10-30 00:30:00+02:00 5.1\n", "2016-10-30 01:30:00+02:00 6.1\n", "2016-10-30 02:30:00+02:00 6.2\n", "2016-10-30 02:30:00+01:00 6.1\n", "2016-10-30 03:30:00+01:00 6.1\n", "2016-10-30 04:30:00+01:00 5.7\n", "2016-10-30 05:30:00+01:00 5.2\n", "2016-10-30 06:30:00+01:00 4.7\n", "2016-10-30 07:30:00+01:00 4.1\n", "2016-10-30 08:30:00+01:00 3.9\n", "2016-10-30 09:30:00+01:00 3.5\n", "dtype: float64" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "temp_series_paris_naive.tz_localize(\"Europe/Paris\", ambiguous=\"infer\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 기간\n", "\n", "`pd.period_range()` 함수는 `DatetimeIndex`가 아니라 `PeriodIndex`를 반환합니다. 예를 들어 2016과 2017년의 전체 분기를 가져와 보죠:" ] }, { "cell_type": "code", "execution_count": 40, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.038037Z", "iopub.status.busy": "2020-10-16T07:31:26.036774Z", "iopub.status.idle": "2020-10-16T07:31:26.043054Z", "shell.execute_reply": "2020-10-16T07:31:26.044094Z" } }, "outputs": [ { "data": { "text/plain": [ "PeriodIndex(['2016Q1', '2016Q2', '2016Q3', '2016Q4', '2017Q1', '2017Q2',\n", " '2017Q3', '2017Q4'],\n", " dtype='period[Q-DEC]', freq='Q-DEC')" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "quarters = pd.period_range('2016Q1', periods=8, freq='Q')\n", "quarters" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`PeriodIndex`에 숫자 `N`을 추가하면 `PeriodIndex` 빈도의 `N` 배만큼 이동시킵니다:" ] }, { "cell_type": "code", "execution_count": 41, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.052480Z", "iopub.status.busy": "2020-10-16T07:31:26.051248Z", "iopub.status.idle": "2020-10-16T07:31:26.055609Z", "shell.execute_reply": "2020-10-16T07:31:26.056455Z" } }, "outputs": [ { "data": { "text/plain": [ "PeriodIndex(['2016Q4', '2017Q1', '2017Q2', '2017Q3', '2017Q4', '2018Q1',\n", " '2018Q2', '2018Q3'],\n", " dtype='period[Q-DEC]', freq='Q-DEC')" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "quarters + 3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`asfreq()` 메서드를 사용하면 `PeriodIndex`의 빈도를 바꿀 수 있습니다. 모든 기간이 늘어나거나 줄어듭니다. 예를 들어 분기 기간을 모두 월별 기간으로 바꾸어 보죠:" ] }, { "cell_type": "code", "execution_count": 42, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.065095Z", "iopub.status.busy": "2020-10-16T07:31:26.064006Z", "iopub.status.idle": "2020-10-16T07:31:26.068838Z", "shell.execute_reply": "2020-10-16T07:31:26.069767Z" } }, "outputs": [ { "data": { "text/plain": [ "PeriodIndex(['2016-03', '2016-06', '2016-09', '2016-12', '2017-03', '2017-06',\n", " '2017-09', '2017-12'],\n", " dtype='period[M]', freq='M')" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "quarters.asfreq(\"M\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "기본적으로 `asfreq`는 각 기간의 끝에 맞춥니다. 기간의 시작에 맞추도록 변경할 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 43, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.079083Z", "iopub.status.busy": "2020-10-16T07:31:26.077918Z", "iopub.status.idle": "2020-10-16T07:31:26.082533Z", "shell.execute_reply": "2020-10-16T07:31:26.083439Z" } }, "outputs": [ { "data": { "text/plain": [ "PeriodIndex(['2016-01', '2016-04', '2016-07', '2016-10', '2017-01', '2017-04',\n", " '2017-07', '2017-10'],\n", " dtype='period[M]', freq='M')" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "quarters.asfreq(\"M\", how=\"start\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "간격을 늘릴 수도 있습니다:" ] }, { "cell_type": "code", "execution_count": 44, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.092258Z", "iopub.status.busy": "2020-10-16T07:31:26.091161Z", "iopub.status.idle": "2020-10-16T07:31:26.096928Z", "shell.execute_reply": "2020-10-16T07:31:26.095946Z" } }, "outputs": [ { "data": { "text/plain": [ "PeriodIndex(['2016', '2016', '2016', '2016', '2017', '2017', '2017', '2017'], dtype='period[A-DEC]', freq='A-DEC')" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "quarters.asfreq(\"A\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "물론 `PeriodIndex`로 `Series`를 만들 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 45, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.107793Z", "iopub.status.busy": "2020-10-16T07:31:26.106610Z", "iopub.status.idle": "2020-10-16T07:31:26.112111Z", "shell.execute_reply": "2020-10-16T07:31:26.111095Z" } }, "outputs": [ { "data": { "text/plain": [ "2016Q1 300\n", "2016Q2 320\n", "2016Q3 290\n", "2016Q4 390\n", "2017Q1 320\n", "2017Q2 360\n", "2017Q3 310\n", "2017Q4 410\n", "Freq: Q-DEC, dtype: int64" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "quarterly_revenue = pd.Series([300, 320, 290, 390, 320, 360, 310, 410], index = quarters)\n", "quarterly_revenue" ] }, { "cell_type": "code", "execution_count": 46, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.140793Z", "iopub.status.busy": "2020-10-16T07:31:26.133036Z", "iopub.status.idle": "2020-10-16T07:31:26.258810Z", "shell.execute_reply": "2020-10-16T07:31:26.260006Z" } }, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAX4AAAEECAYAAAAvY19bAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8vihELAAAACXBIWXMAAAsTAAALEwEAmpwYAAA4BElEQVR4nO3dd3hc5ZXA4d/RqMuyZKu4SLJkI9nCNu5FptjGDmAIhN4xIYGQsoEkJBtINo2UTUiDBLJJCJAFTA2B0AkBDTYGN+GGy4wtuUluM+pW12i+/UMjr2Nsq83MnXLe59HD6M4tR+bO0dV3zz2fGGNQSikVPWKsDkAppVRwaeJXSqkoo4lfKaWijCZ+pZSKMpr4lVIqymjiV0qpKBNrdQAAmZmZpqCgwOowlFIqrHz00UfVxpis/m4XEom/oKCAsrIyq8NQSqmwIiJ7B7KdDvUopVSU0cSvlFJRRhO/UkpFGU38SikVZTTxK6VUlNHEr5RSUUYTv1JKhaG9Nc0D3lYTv1JKhRljDDc+smbA22viV0qpMFPhbqaqrnXA22viV0qpMGN3uAa1vSZ+pZQKM3aniwkjUge8vSZ+pZQKI0faOlm3p5aFxf3uzXaUJn6llAojH5RX09llOHdC9oD3oYlfKaXCiN3hJjUxlpn5wwa8D038SikVJowx2J0u5hdlEWcbePrWxK+UUmFi64FGXEfaWThh4OP7oIlfKaXCxnvO7jLOhYMY3wdN/EopFTbsTjdTctPISk0Y1H408SulVBioa+5gw766QV/tgyZ+pZQKCyt2uvEaWFSsiV8ppaKC3eEiIyWeKTlpg95XnxO/iNhEZIOIvOb7fqyIrBGRchF5TkTifcsTfN+X+94vGHSUSikVxbq8huU73CwYn0VMjAx6f/254v8asP2Y7+8D7jfGFAJ1wK2+5bcCdb7l9/vWU0opNUAbK+upa+nkXD8M80AfE7+I5AKfBh7xfS/AIuAF3yqPA5f5Xl/q+x7f+4t96yullBqA95wuYgTmFw2ufr9HX6/4HwC+DXh932cA9cYYj+/7KiDH9zoHqATwvd/gW//fiMjtIlImImVut3tg0SulVBQodbiYmT+MtOQ4v+yv18QvIhcDLmPMR345oo8x5mFjzCxjzKysLP/8FlNKqUhzuLGNrQca/TbMAxDbh3XOAj4jIhcBicBQ4HdAuojE+q7qc4H9vvX3A3lAlYjEAmlAjd8iVkqpKLLc2T0iMphunMfr9YrfGPMdY0yuMaYAuA4oNcbcCNiBq3yrfRZ42ff6Fd/3+N4vNcYYv0WslFJRpNThYlRaIsUjBz7xyvEGU8d/N3CXiJTTPYb/qG/5o0CGb/ldwD2DC1EppaJTh8fLyvJqFk7Ixp81Mn0Z6jnKGPMe8J7v9S5gzgnWaQOu9kNsSikV1cr21tLU7uHcQXbjPJ4+uauUUiHK7nARb4vhrMJMv+5XE79SSoUou9PN3HHDSUno1+BMrzTxK6VUCKqsbaHc1eSXbpzH08SvlFIhqGfSFX+P74MmfqWUCkmlDhcFGcmMyxri931r4ldKqRDT1tnFhxU1ARnmAU38SikVclbtqqHd4/Vrm4ZjaeJXSqkQY3e4SIqzMXfs8IDsXxO/UkqFEGMMpQ4XZxVmkBhnC8gxNPGrsFbf0mF1CEr5VYW7maq61oCN74MmfhXGHIcamfnTd/jn1kNWh6KU39gdvjLOAI3vgyZ+Fcbe3nqYLq/hsZW7rQ5FKb+xO11MGJFKTnpSwI6hiV+FLbvThQis2V3LjsNHrA5HqUE70tbJuj21LCwO7ORUmvhVWKppamdjZT03l+QTHxvDstV7rQ5JqUH7oLyazi7DogCO74MmfhWmVux0YwxcMSOXi6eM4sX1+2lq9/S+oVIhzO5wk5oYy4z8YQE9jiZ+FZbsDjeZQ+I5IyeNpSX5NLV7eGnD/t43VCpEGWOwO13ML8oizhbY1KyJX4UdT5eX5TvcLBifTUyMMC0vnck5Q1m2ai86y6cKV1sPNOI60h7Qap4emvhV2NlYWU9Dayfn+m6AiQhLS/JxHj7Cuj11Fken1MD0dONcMD6wN3ZBE78KQ3anC1uMcE7R/39APjM1h6GJsTypN3lVmLI73UzJTSMrNSHgx9LEr8JOqcPNzPxhpCXFHV2WFG/j6ll5vLXlIK4jbRZGp1T/1TV3sGFfHecGuJqnhyZ+FVYONbSx/WDjCT8gN84dQ2eX4bm1lRZEptTArdjpxmsC+7TusTTxq7BydFaiEzzgMi5rCOcUZfL02n14urzBDk2pAbM7XGSkxDMlJy0ox9PEr8JKqcPF6LREJoxIPeH7N5Xkc7ChjXd9/U6UCnVdXtNdpTYhi5gYCcoxNfGrsNHu6eKD8moWFmcjcuIPyOLibEanJeqTvCpsbKysp66lM2jj+9CHxC8iiSKyVkQ2ichWEbnXt3yxiKwXkY0islJECn3LE0TkOREpF5E1IlIQ4J9BRYmyPXU0d3Sd8gMSa4vhhrljeH9nNbvcTUGMTqmBec9XpTa/KPBlnD36csXfDiwyxkwFpgFLRKQE+CNwozFmGvA08D3f+rcCdcaYQuB+4D5/B62iU6nDRbwthrMKM0653jWz84izCctW7wtSZEoNXKnDxcwxw0hLjut9ZT/pNfGbbj2XTnG+L+P7GupbngYc8L2+FHjc9/oFYLGc7O9ypfrB7nQxd9xwkuNjT7ledmoiSyaP4m8fVdLSof17VOg63NjG1gONAe/Gebw+jfGLiE1ENgIu4F/GmDXAbcAbIlIFLAV+4Vs9B6gEMMZ4gAbgE5doInK7iJSJSJnb7R70D6Ii296aZna5m/s8Drq0JJ8jbR5e3XSg95WVsshyZ3fuC+b4PvQx8RtjunxDOrnAHBGZDHwDuMgYkwv8Ffhtfw5sjHnYGDPLGDMrKyu4v+1U+OmZlWhRH+ucZxcMY8KIVJ7Q/j0qhJU6XIxKS6R45Imr1AKlX1U9xph6wA5cCEz1XfkDPAec6Xu9H8gDEJFYuoeBavwRrIpedqebsZkpFGSm9Gl9EWHpvHy2HmhkY2V9YINTagA6PF5WllezcMLJq9QCpS9VPVkiku57nQScB2wH0kRkvG+1nmUArwCf9b2+Cig1esmlBqG1o4tVu2pYOKF/fxleNj2HIQnav0eFprK9tTS1ezi3n+e1P/Tlin8UYBeRzcA6usf4XwO+APxdRDbRPcb/n771HwUyRKQcuAu4x/9hq2jyYUU1HR5vn4d5egxJiOWKGTm8tvkgtc0dAYpOqYGxH61Sywz6sU9dHgEYYzYD00+w/CXgpRMsbwOu9kt0StFdzZMUZ2PO2OH93vamknyeWLWX58sq+dKC0wIQnVIDY3e6mTtuOCkJvaZhv9Mnd1VIM8Zgd7g5qzCThFhbv7cfPyKVuWOH89SavXR5dcRRhYbK2hbKXU0sDHI1Tw9N/Cqk7XQ1sb++td/DPMdaOi+fytpWVuzQsmEVGuzO/lWp+ZsmfhXSeso4+3tj91gXTBpJVmqC3uRVIcPucFGQkczYPlap+ZsmfhXS7E4XxSNTGZ2eNOB9xNliuH7OGOxOF5W1LX6MTqn+a+vs4sOKGsuGeUATvwphjW2dlO2p88vkFNfPySNGhGVr9KpfWWtVRQ3tA6hS8ydN/CpkrdxZjcdr/PI4+6i0JM47fQTPr6ukrbPLD9EpNTCDqVLzF038KmTZHS6GJsYyY0y6X/a3dF4+dS2dvPHxQb/sT6n+MsZQ6nBxVmEGiXH9r1LzF038KiR5vQa708388VnE2vxzmp55WgbjslL0Jq+yTIW7iaq61qDNrXsymvhVSNp6oJHqpna/di0UEZaW5LNhXz1b9jf4bb9K9ZXd0V1SbOWNXdDEr0KU3elCBBb4uY/JFTNySYqz8eQqvepXwWd3upgwIpWcQVSp+YMmfhWSSh0upuSmkzkkwa/7TUuK47Lpo3l5034aWjr9um+lTuVIWydrd9daPswDmvhVCKppamdTVX3AuhbeVJJPW6eXF9ZXBWT/Sp3IB+U9VWrWzz+iiV+FnBU73RgTuFmJJo1OY8aYdJat3otX+/eoILE73KQmxjIjf5jVoWjiV6Gn1OEmc0g8Z+SkBewYN88rYHd1Mx9W6BxBKvCMMdidLuaPzyLOT1Vqg2F9BEodw9PlZcUONwvGZxMTE7hZiS48YyTDU+J5YtWegB1DqR5bDzTiOuLfKrXB0MSvQsrGynoaWjs5tziw46AJsTaunZ3HO9sPc6C+NaDHUuo9XzfOBeOtH98HTfwqxJQ6XNhihHOKAv8BuWHOGAzwzNp9AT+Wim52p5upuWlkpfq3Sm2gNPGrkGJ3upmZP4y0pLiAHytveDKLJmTzzNpKOjzegB9PRae65g427Kuz/KGtY2niVyHjUEMb2w82BnUcdOm8fKqb2vnn1kNBO6aKLit2uvEaQqJ+v4cmfhUyrJiVaH5RFmOGJ+uTvCpg7A4XGSnxTAlglVp/aeJXIcPucDE6LZHxI4YE7ZgxMcJNJWNYu6cWx6HGoB1XRYcur2H5DjcLJmQFtEqtvzTxq5DQ7unig/JqFhZnIxLcD8jVM/OIj41hmXbtVH62sbKeupbOkCnj7KGJX4WEsj11NHd0sciCD8iwlHgumTKal9bv50ib9u9R/vOes7tKbX4QqtT6o9fELyKJIrJWRDaJyFYRude3XETkZyKyQ0S2i8idxyz/vYiUi8hmEZkR6B9Chb9Sh4t4WwxnFmZYcvyl8/Jp7ujiHxv2W3J8FZlKHS5mjhlGWnLgq9T6oy9X/O3AImPMVGAasERESoBbgDyg2BhzOvCsb/0LgSLf1+3AH/0cs4pAdqeLueOGkxwfa8nxp+WlMyU3jSdX78UY7d+jBu9wYxtbDzSyMMAPIw5Er4nfdGvyfRvn+zLAl4EfG2O8vvVcvnUuBZ7wbbcaSBeRUf4PXUWKvTXN7HI3Wzr5NHR37dxxuIk1u2stjUNFhuXO7klXrD6vT6RPY/wiYhORjYAL+JcxZg1wGnCtiJSJyJsiUuRbPQeoPGbzKt8ypU7I7ui+ZrD6BtglU0aTlhSnUzP20fIdbn762jbtcHoSpQ4Xo9ISmTAi1epQPqFPid8Y02WMmQbkAnNEZDKQALQZY2YBfwEe68+BReR23y+NMrfb3c+wVSSxO92MzUyhIDPF0jiS4m1cPTOXf245hKuxzdJYQt2+mha++tR6Hlm5mxf1vsgndHi8rCyvZuGE4Fep9UW/qnqMMfWAHVhC95X8i763XgKm+F7vp3vsv0eub9nx+3rYGDPLGDMrKyv0xsBUcLR2dLFqV43lV/s9bizJx+M1PLuusveVo1Rnl5c7n90AAqePGsp9bzloavdYHVZIKdtbS1O7JySHeaBvVT1ZIpLue50EnAc4gH8A5/pWWwDs8L1+BbjZV91TAjQYYw76OW4VIT6sqKbD4w14N86+GpuZwjlFmTy9Zh+eLu3fcyL3/2sHGyvr+cUVU/j5FWfgPtLOg6U7rQ4rpNh7qtROs6ZKrTd9ueIfBdhFZDOwju4x/teAXwBXisjHwM+B23zrvwHsAsrpHgL6it+jVhHD7nSRHG9jztjhVody1M3zCjjU2MY72w9bHUrI+bC8mj8ur+C62Xl8esoopuWlc+WMXB5buZvd1c1Whxcy7E43c8cNJyXBmiq13vSlqmezMWa6MWaKMWayMebHvuX1xphPG2POMMbMM8Zs8i03xpj/MMac5nuvLNA/hApPxhjsDjdnFWaSEGuzOpyjFhVnk5OepDd5j1Pb3MHXn9vIuMwUfnDJxKPL714ygXhbDD97fZuF0YWOytoWyl1NITN8eSL65K6yzE5XE/vrW0PuA2KLEW6YO4YPymsodzX1vkEUMMbwn3/bRH1LJ7+/fvq/PW+RPTSROxYX8c52F8t3aKFGT7PBUOrGeTxN/MoyPWWcCyeExvj+sa6ZlUecTXhqjV71Azz+4R7edbj4zkXFTBr9yS6TnzurgIKMZH786lY6o/zeiN3hoiAjmbEWV6mdiiZ+ZRm700XxyFRGpydZHconZKUmcOHkUbzwURUtHdFdsbLtQCP//YaDRcXZ3HJmwQnXSYi18b1PT6TC3cwTUdziuq2ziw8rakL6ah808SuLNLZ1UranLqQ/IDfPy+dIm4dXNh6wOhTLtHR4uOOZ9aQnx/Grq6acsiZ98enZzB+fxQPv7KCmqT2IUYaOVRU1tHu8ITd8eTxN/MoSK3dW4/GakP6AzMwfRvHIVJ5YFb39e37y2jZ2VTdz/7XTyBhy6vliRYQfXHw6rR1d/PrtHadcN1LZnS6S4kKrSu1ENPErS9gdLoYmxjJjTLrVoZyUiLB0Xj7bDjayfl+91eEE3eubD/LM2kq+tOA0zirM7NM2hdmp3DyvgGfX7WPL/oYARxhajDGUOlycVZhJYlzoVKmdiCZ+FXRer8HudDN/fBaxttA+BS+blsOQhNiom6Slqq6Fe17czNS8dO46b3y/tv3ap4oYlhzPva9ujaq/lCrcTVTVtYbMw4inEtqfOhWRth5opLqpPaSHeXqkJMRy5YwcXt98MGrGrT1dXr727EaMgQevm05cP385pyXF8a3zJ7BuTx2vbY6eh/btju5S1oVhcF5r4ldBZ3e6EIEFIVjGeSI3leTT0eXl+bIqq0MJit+/u5OP9tbxs8snMyYjeUD7uHZ2HpNGD+Xnb2yntaPLzxGGpp4qtZwQrFI7niZ+FXSlDhdTctPJ7OVmYagoGpHKvHEZLFu9l64Ib0G8elcND9nLuWpmLpdOG3g3dVuM8MNLJnGgoY0/La/wY4Sh6UhbJ2t314bF1T5o4ldBVtPUzqaqes4Nk6v9Hkvn5bO/vpX3nK7eVw5Tdc0dfOO5jeRnpHDvZyYNen9zxg7n4imj+NPyCqrqWvwQYej6oLynSi08zmtN/CqoVux0Y0xozkp0KudNHEF2akLE9u8xxnD33zdT3dTO76+b7rfmYt+96HRE4OdvOPyyv1Bld7hJTYxlZv4wq0PpE038KqhKHW4yh8Qz+QSP/YeyOFsM188Zw/IdbvbWRF4XymVr9vH2tsPcvaSYM3L99/9mdHoSX15QyOsfH2T1rhq/7TeUGGOwO11hUaXWIzyiVBHB0+VlxQ43C8ZnExMTerMS9eb6OWOIEeHpNfusDsWvnIeO8NPXtrFgfBafP2us3/d/+/xx5KQnce+r2yLyHsnWA424joRHlVoPTfwqaDZW1tPQ2hl2wzw9RqYlcsGkETxXVklbZ2RUqrR1dnHHM+tJTYzj11dPDcgv5KR4G9+96HS2H2zkmbWR9UsTOHrfJxSbDZ6MJn4VNKUOF7YY4eyivj0FGopuKsmnvqUzYurTf/r6NnYcbuK310wlKzVwVVYXnTGSuWOH85u3nTS0dAbsOFYodbiYmpsWNlVqoIlfBZHd6WZm/jDSkuKsDmXA5o3L4LSslIi4yfvWlkMsW72P2+ePY/74wF6tinSXdza0dnL/O5HTx6e2uYMNlfVhU8bZQxO/CopDDW1sP9gYtsM8PUSEpSX5bKqsZ3NVvdXhDNiB+lbu/vtmzshJ41vnTwjKMSeOHsr1c8bw5Oq97Dh8JCjHDLT3w7RKTRO/CoqjsxKF2ZXRiVwxM5ekOFvY9u/p8hq+/txGPF1efn/9dOJjg5cGvnn+BFLibfzktW0R0cen1OEiIyWeM3LCq0pNE78KCrvDxei0RMaPGGJ1KIM2NDGOy6bn8PLGA2E5Xv0Hezlrd9fyk8smB32WqOEp8XzjvPG8v7Oaf20L78nsu7yG5TvcLJiQFXZVapr4VcC1e7r4oLyac4uzTzmRRzhZWpJPu8fL3z6qtDqUfinbU8sD7+zg8uk5XDEj15IYbirJpyh7CD99fXtYV0dtrKynviU8q9Q08auAW7e7juaOrogY5ukxcfRQZuUPY9nqvXjDpDa9oaWTrz27kdxhyfz40sG3ZBioOFsMP7xkEvtqW3jsg92WxTFYdl+V2jmF4VPG2UMTvwo4u9NFfGwMZxZmWB2KXy2dl8+emhZWlldbHUqvjDHc8+JmDje28fvrp5OaaG1l1dlFmZw3cQQPlZZzuLHN0lgGyu50MXPMMNKSw69KTRO/Cji700XJuAyS4/3T/yVULJk8koyU+LAo7Xx2XSVvbjnEty6YwLS8dKvDAeB7nz4dT5fhvjfDr4/P4cY2th5oDOk5o0+l18QvIokislZENonIVhG597j3fy8iTcd8nyAiz4lIuYisEZGCAMStwsTemmZ2uZvDpmthfyTE2rh2dh7vbj/M/vpWq8M5qZ2Hj3Dvq1s5uzCT288ZZ3U4R+VnpHDbOWN5ccN+1u+rszqcful5WjccZts6kb5c8bcDi4wxU4FpwBIRKQEQkVnA8e3obgXqjDGFwP3Aff4LV4UbuyNyyjhP5Ia5YwB4ek1oXvV3t2TYQEp8LL+9JjAtGQbjK+cWkp2awL2vbA2beyXQ3Y1zVFoiE0akWh3KgPSa+E23niv6ON+XEREb8Cvg28dtcinwuO/1C8BiiZRSDtVvdqebcZkpFAS5bDBYcocls6h4BM+tq6TdE3oVKr9404Hj0BF+ffVUsocmWh3OJwxJiOWeC4vZVNXA39eHxwxnHR4vK8O8Sq1PY/wiYhORjYAL+JcxZg3wVeAVY8zxTUtygEoAY4wHaAAi666e6pOWDg+rdtWE3ePs/bV0Xj7VTR28teWQ1aH8m3e2HeZ/P9zD588aG9Jj0ZdNy2H6mHTue8vJkbbQfy6ibG8tTe2esP4rtk+J3xjTZYyZBuQCc0RkPnA18OBADywit4tImYiUud3uge5GhbBVFTV0eLxhOw7aV+cUZpKfkRxST/IeamjjP1/YxMRRQ7n7wuC0ZBioGN80jdVN7TxkL7c6nF7ZHS7ibTGceVr4Xs/2q6rHGFMP2IFzgUKgXET2AMki0vN/bD+QByAisUAa8IkZGIwxDxtjZhljZmVlRXZiiFZ2p4vkeBtzxg63OpSAiokRbpqbz7o9dWw/2Gh1OHR5Dd94biNtnV4evGE6CbE2q0Pq1bS8dK6amctjK3ezuzq0J7qxO93MHTfcb7OUWaEvVT1ZIpLue50EnAd8ZIwZaYwpMMYUAC2+m7kArwCf9b2+Cig1kdCUQ/WLMQa7w81ZhZlhkXgG6+pZuSTExoTEVf+fllewalcN9146idOywqdFxreXTCDeFsPPXt9mdSgnVVnbQrmrKayHeaBvV/yjALuIbAbW0T3G/9op1n8UyPD9BXAXcM/gw1ThZqerif31rWH/Aemr9OR4PjN1NC9t2E+jhePU6/fV8dt/7eCSqaO5eqY1LRkGKjs1kTsWF/HOdhfLd4Tm8O/RZoMhfM+kL/pS1bPZGDPdGDPFGDPZGPPjE6wz5JjXbcaYq40xhcaYOcaYXf4OWoW+o2WcET6+f6yl8/Jp6ejipfX7LTl+Y1sndz6zgVFpifzs8slhWXHyubMKKMhI5sevbqWzy2t1OJ9gd7gYm5kS9OZ2/qZP7qqAKHW4KB6Zyqi0JKtDCZopuelMzU3jydV7g95y2BjDd1/8mIMNbfzuuukMtbglw0AlxNr4/sUTqXA388Qq64fNjtXW2cWHFTVhNcXiyWjiV37X2NZJ2d66sP9zeCBuKsmn3NXE6l21QT3u3z6q4rXNB7nrvPHMzD/+mcrwsqg4m/njs3jgnR3UNLVbHc5RqypqaPd4I2L4UhO/8ruVO6vp8pqwbFc7WJdMHU16clxQb/JWuJv40StbmTcugy8tOC1oxw0UEeEHF0+ktaOLX7/ttDqco+xOF0lxNuaOC/8qNU38yu9KHS6GJsYyPUSagQVTYpyNa2bl8c+th4LSdbLd08Wdz2wgITaG+6+dhi3EWjIMVGH2ED57ZgHPrqtky/4Gq8PBGEOpwxUxVWqa+JVfeb2G95xu5o/PItYWnafXjXPH4PEanlm7L+DH+uVbTrYeaORXV01lZFrotWQYjDsXFzE8OZ57X91q+TSNFe4mqupaI6ZYITo/mSpgth5opLqpPSqHeXrkZ6SwYHwWz6zdF9DKFLvDxaMrd/PZefl8auKIgB3HKmlJcXzrggms21PHa5uP7wwTXHZHd3lpJIzvgyZ+5WelDhciMH98ZFwZDdTSknwON7bzToDmlXU1tvGtv22ieGQq37no9IAcIxRcMyuPSaOH8vM3ttPaYV0TPLuzu0ptdHpkVKlp4ld+ZXe6mJKbTuaQBKtDsdS5xdnkpCcFZJIWr9fwzb9tornDw4PXTycxLvzHnE/G5uvjc6ChjT8ur7AkhiNtnazdXRtRzQY18Su/qWlqZ1NVPYsi6AMyULYY4Ya5Y/iwooZy1xG/7vsv7+/i/Z3V/PCSSRSFaT/4/pgzdjiXTB3Nn5dXUFXXEvTjf1BejSfCqtQ08Su/Wb7DjTHR9bTuqVw7O494WwzLVvvvJu+mynp+9U8nF50xkutm5/ltv6HuOxcWIwI/fyP40zTaHW5SE2OZMSY96McOFE38ym/sTjeZQxKYPDrN6lBCQuaQBC46YyR//6iK5nbPoPd3pK2TO5/dwIihifz88ilh2ZJhoEanJ/HlBYW8/vFBVlV8otlvwBhjsDtdEVelFjk/ibKUp8vLih1uFk7ICrnp/ay0dF4+R9o9vLzxwKD39YOXt1JZ28ID100jLTk8WzIMxhcXjCMnPYl7X91KV5Cmadx6oBHXkfaIG77UxK/8YkNlPQ2tnRFT7uYvM8YM4/RRQ3li1Z5B1aK/uL6Klzbs52uLxzO7IPyfHB2IxDgb373odByHjgTlGQn4/0nVF0RAf55jaeJXfmF3uLDFCGcXZVodSkgREZaW5OM4dIT1++oGtI891c18/x9bmDN2OF9dVNj7BhHsojNGMnfscH7ztpOGlsC3vy51uJiamxZxVWqa+JVf2J1uZuUPIy0p+oYgenPptNGkJsQOqNtkh8fLnc9uINYWwwMR1JJhoES6yzsbWju5/50dAT1WbXMHGyrrI7LZoCZ+NWgHG1rZfrAxIj8g/pCSEMuVM3N54+ODVPez2+Rv3nayuaqB+66cEjEPDw3WxNFDuX7OGJ5cvZcdh/1bKnus93f6qtQicPhSE78atPeckfU4eyDcVJJPZ5fhuXWVfd5mxQ43f16xixvnjmHJ5JEBjC78fPP8CaTE2/jxq9sC1sen1OEic0g8Z+REXpWaJn41aHaHi9FpiYwfET7zuwZbYfYQzjwtg6fX7OtTRUp1Uzt3Pb+J8SOG8P2LJwYhwvAyPCWeu84bz8ryav4VgLYYXV7D8h1uFozPjsgqNU38alDaPV2sLK/m3OLsqKorH4ilJfnsr289Oi3lyXi9hm8+v4kjbZ08eP2MiG7JMBg3luRTlD2En76+nbZO//bx2VhZT31LZ8Q+jKiJXw3Kut11tHR06TBPH3xq4ghGDE3giV769zz2wW6W73DzvYsnMmFk5LdkGKg4Www/vGQS+2pbeHTlbr/uu6dK7ZwiTfxKfYLd6SI+NoYzCzOsDiXkxdliuGFOPit2uNlT3XzCdbbsb+C+txycP3EEN80dE+QIw8/ZRZmcP3EEf7CX+3XiG7vTxcwIrlLTxK8Gxe5wUTIug+T4WKtDCQvXzckjNkZ4as0nr/qb2z3c8cwGMlISuO/K6GrJMBj/9enT8XQZ7nvTP318Dje2sfVAY0T/FauJXw3YnupmdlU3c26EPdUYSCOGJnLBpJE8X1b1iXHpH76ylT01zTxw3TSGpcRbFGH4yc9I4bZzxvLihv0DfkjuWD1P60bq+D5o4leDcPQDEsFXRoFwU0k+Da2dvLrp//v3vLxxPy98VMUd5xZSMk6HzfrrP84tJDs1gXtf2Yp3kH187A43o9MSmRDBLa97Tfwikigia0Vkk4hsFZF7fcufEhGniGwRkcdEJM63XETk9yJSLiKbRWRGoH8IZY1Sp5txmSkUZKZYHUpYKRk3nMLsISzz3eTdV9PC917awsz8Ydy5uMji6MJTSkIs91xYzKaqBv6+vmrA++nweFlZXs3CCK9S68sVfzuwyBgzFZgGLBGREuApoBg4A0gCbvOtfyFQ5Pu6Hfijn2NWIaClw8PqXTURNStRsPT079lU1cBHe2u589kNIPC766ZFVOvfYLtsWg7Tx6Rz31tOjrQNrI9P2Z5amto9Ef9XbK9nmenW5Ps2zvdljDFv+N4zwFog17fOpcATvrdWA+kiMioQwSvrrKqoocPjjehx0EC6YkYOyfE2bnu8jI2V9fziiinkDku2OqywFhMj/OiSSVQ3tfOQvXxA+7A7XcTbYjgrwqvU+nR5ISI2EdkIuIB/GWPWHPNeHLAUeMu3KAc49rn0Kt+yiHOgvpUvPlnGb952Buyx8VBV6nCRHG9jztjobBE8WKmJcVw+PYe6lk6um53Hp6fotZE/TM1L56qZuTy2cje7T1Iyeyp2p5u544ZHfJVanxK/MabLGDON7qv6OSIy+Zi3/wdYYYx5vz8HFpHbRaRMRMrcbnd/NrWcMYYX11dxwQMreGe7iwdLy7nvrehJ/sYY3nO6Oaswk4RYfap0oO5cXMSdi4v4wSXaksGfvr1kAgmxNn762rZ+bVdZ20K5qynih3mgn1U9xph6wA4sARCRHwJZwF3HrLYfOHYy0FzfsuP39bAxZpYxZlZWVvgMF9Q2d/CVp9Zz1/ObKB6ZSuk3F3Dj3DH8aXkFv3t3p9XhBcVOVxP761uj4gMSSCOGJnLXeeMj/uoy2LJTE7ljUSHvOlxHK8/6wu5bN5ImVT+ZvlT1ZIlIuu91EnAe4BCR24ALgOuNMd5jNnkFuNlX3VMCNBhjDvo/9OB7d/thzr9/Be9ud3HPhcU8e/s88jNS+Mmlk7lqZi4PvLOT/3lvYGOL4aTUEfl1ziq83XJWAQUZyfzktW10dnl734DuhxHHRkmVWl8uNUYBj4uIje5fFM8bY14TEQ+wF1jlK3t60RjzY+AN4CKgHGgBPheQyIOoqd3DT1/bxrPrKikemcqTt87h9FFDj74fEyPcd+UUOjxefvmWk4RYG7eePdbCiAPL7nBRPDKVUWnaH16FpoRYG9+/eCK3Pl7G4x/u4bZzxp1y/daOLj6sqOGGKGmT0WviN8ZsBqafYPkJt/VV+fzH4EMLDWt31/LNv21kf10rX1l4Gl/7VNEJx7VtMcJvr5lKh8fLT17bRkJsDDeV5FsQcWA1tnVStreO2+ef+oOklNUWFWezYHwWv3t3J5dNzznl9Imrd9XQ7vFGxTAP6JO7J9Xu6eLnb2zn2odXIQjPf3Ee315SfMqbmbG2GH5//XQWFWfzvX9s4fmyvk+6ES7e31FNl9dEzQdEhS8R4fsXT6S1o4vfvO085bp2p4ukuOipUtPEfwJbDzTwmQc/4M8rdnH9nDG8+bVzmFXQtxMiPjaG/7lxBucUZXL33zfz8sZP3NcOa3ani6GJsUzPS7c6FKV6VZg9hM+eWcCz6yrZsr/hhOsYYyh1uKKqSk0T/zE8XV7+YC/nsj98QG1LB3/93Gz++/IzSEnoX9VFYpyNh5fOYk7BcO56fhNvfhwR97bxervLOOePz9InTFXYuHNxEcOT47n31a0nLLmucDdRVdcaVX/F6qfXZ091M9f8eRW/+qeT8yeO5O2vzx9UuWJSvI3HbpnN1Nw07nx2A+9u9//0cMG25UAD1U3tUfUBUeEvLSmOb10wgXV76nh18ycvwuyO7ueIFkZRl9moT/zGGJat3suFv3ufclcTv7tuGg/dMN0vbXFTEmL53893VwB9edl6VuwIrwfVjmd3uBGB+eOj5wOiIsM1s/KYNHooP39jO60d/94O2+7srlIbnR49VWpRnfgPN7Zxy1/X8b1/bGFWwTDe/sYCLp2W49eufEMT43ji83MYl5XC7U+Wsaqixm/7Dja708WU3PRTVkcoFYpsMcKPPjOJgw1t/HF5xdHlR9o6Wbu7lnOj7K/YqE38r246wPn3r2DN7hp+cukknvj8HEamJQbkWOnJ8Tx121zyhiVz6+Pr+GhvbUCOE0g1Te1sqqpnkT6tq8LU7ILhXDJ1NH9eXkFVXQsAH5RX4/GaqHsKPeoSf31LB3c+s4E7ntnA2MwU3rjzHJbOKwh47+2MIQk8ddtcslMTuOWxdWyuqg/o8fxt+Q43xujTuiq8fefCYkTg5290T9Nod7gZmhjLjDHp1gYWZFGV+JfvcHPBAyt44+ODfOv88bzwpXmMyxoStONnD03k6S+UkJYcx9JH17LtQGPQjj1YdqebzCEJTB6dZnUoSg3Y6PQkvrKwkNc/PsiHFdXYna6orFKLip+2pcPD9/7xMZ99bC1DE+P4x3+cxVcXFVnyP3t0ehLPfKGE5HgbNz26hp2HjwQ9hv7ydHlZscPNwglZxMRE7qxEKjrcPn8cOelJfO3ZjbiOtEfdMA9EQeL/aG8dF/3ufZ5as48vnDOWV+84m8k51l615g1P5ukvlGCLEW54ZM2A+oYH04bKehpaO6PyA6IiT2Kcjf/69Om4j7QjAguiqIyzR8Qm/g6Pl1/908HVf/qQzi7DM18o4b8+PZHEuNB4Mm9sZgpP3zaXLq/hhr+sprK2xeqQTsrucGGLEc4uyrQ6FKX84sLJIzmnKJOSsRlRWaUWkYnfeegIl/3hA/5gr+Cqmbm89fVzKBkXelOpFY1IZdmtc2np6OL6v6zmQH2r1SGdkN3pZlb+MNKS4qwORSm/EBEeu2U2j39+jtWhWCKiEn+X1/DwigoueXAlhxvbeHjpTH551VRSE0M3YU0cPZQnb51DQ0snN/xlNa7GNqtD+jcHG1rZfrAx6uqcVeSLs8UQHxtRKbDPIuanrqxt4fq/rOa/33CwcEIW//zGfM6fNNLqsPpkSm46//v5ObiOtHPDI2uobmq3OqSj3nN2P22s4/tKRY6wT/zGGJ5bt48lD6xg+4FGfn31VP68dGbYjdvNzB/GY7fMpqquhZseWUN9S4fVIQHd4/s56UmMHxG8slelVGCFdeJ3H2nnC0+UcfffP2ZKbjpvfv0crpqZG/CHsQKlZFwGf7l5Fruqm1n66Foa2zotjafd08XK8moWTsgK239TpdQnhW3if2vLQS54YAUrdlbz/Ysn8tRtc8kdlmx1WIN2TlEWf7xxBo5Djdzy2Fqa2j2WxbJudx0tHV06zKNUhAm7xN/Y1sldz2/kS8vWk5OexOt3nM2tZ4+NqAeLFp8+ggevn86mqgY+/7/rPtFNMFjsThfxsTGcWRh6FVFKqYELq8T/QXk1S+5fwcsbD3Dn4iJe/MqZFI1ItTqsgFgyeRS/vWYq6/bUcvuTZbR1Bj/52x0uSsZlkBzfv4lolFKhLSwSf1tnF/e+upUbH1lDYpyNv3/5TO46bzxxEd5f49JpOfzyyim8v7Oarzy1ng6PN2jH3lPdzK7qZs6NwqcalYp0IX8pt7mqnm88t5EKdzO3nFnA3UuKSYoPjadvg+HqWXl0dHn5r5e2cMcz63nohhlB+YX3ntMFaBmnUpEoZBN/p2/+2wdLy8lOTWDZrXOjtmXAjXPzae/08uPXtnHX85t44Npp2AJ8T6PU6WZcZgoFmSkBPY5SKvhCMvGXu5q46/mNbK5q4PLpOfzoM5Oivl3A588eS7vHy31vOUiIjeGXV04J2A3tlg4Pq3fVcNPc/IDsXyllrV4Tv4gkAiuABN/6LxhjfigiY4FngQzgI2CpMaZDRBKAJ4CZQA1wrTFmT1+C8XoNj6/awy/edJAcb+N/bpzBRWeMGtAPFom+vPA02j1dPPDOTuJjY/jZZZMDUl+/qqKGDo9XJ1VXKkL15Yq/HVhkjGkSkThgpYi8CdwF3G+MeVZE/gTcCvzR9986Y0yhiFwH3Adc29tB9te38p9/28SHFTUsKs7mF1eeQXZqYKZCDGdfW1xEu8fLH9+rICE2hh9cPNHvyb/U4SI53sbsscP8ul+lVGjoNfEbYwzQ5Ps2zvdlgEXADb7ljwM/ojvxX+p7DfAC8JCIiG8/J1Tf0sGS+1fgNYZfXHEG187O0ydFT0JE+PYFE2jv9PLYB7tJiLVx95IJfvv3MsbwntPNWYWZJMRGz010paJJn8b4RcRG93BOIfAHoAKoN8b0PFZaBeT4XucAlQDGGI+INNA9HFR9sv1X1rXymVGp/ObqaYzJCP+nbwNNRPj+xafT7uniT8srSIyL4eufGu+Xfe90NbG/vpWvLir0y/6UUqGnT4nfGNMFTBORdOAloHiwBxaR24HbATJyxvLs7fMCXqkSSUSEn1w6mXaP9+iY/1cWDj5Zlzq6yzgXav2+UhGrX1U9xph6EbED84B0EYn1XfXnAvt9q+0H8oAqEYkF0ui+yXv8vh4GHgaYNWuW0aTffzExwn1XTqHD4+WXbzlJiLVx69ljB7VPu8NF8chURqUl+SlKpVSo6fVJIBHJ8l3pIyJJwHnAdsAOXOVb7bPAy77Xr/i+x/d+6anG99Xg2GKE314zlQsnj+Qnr21j2eq9A95XY1snZXvrtJpHqQjXlyv+UcDjvnH+GOB5Y8xrIrINeFZEfgpsAB71rf8o8KSIlAO1wHUBiFsdI9YWw++um07Hso/43j+2EB8bwzWz8vq9n/d3VNPlNTrbllIRri9VPZuB6SdYvgv4xISVxpg24Gq/RKf6LD42hj/cOMM3P8FmEmJjuHRaTu8bHsPudJGWFMf0vPTABKmUCgmR3eUsyiTG2Xh46SzmFAznruc38ebHB/u8rdfbXcY5f3wWsRHe/E6paKef8AiTFG/jsVtmMy0vnTue2cC72w/3abstBxqobmrXbpxKRQFN/BEoJSGWv35uNhNHD+XLy9azYoe7123sDjcisGC8Jn6lIp0m/gg1NDGOJz4/h3FZKdz+ZBmrKj5RUftv7E4XU3PTyQizSeqVUv2niT+CpSfH89Rtc8kblsytj6/jo721J1yvpqmdTVX12ntfqSihiT/CZQxJ4Knb5jJiaCK3PLaOzVX1n1hn+Q43xsC5xTrMo1Q00MQfBbKHJvLUbXNJS45j6aNr2Xag8d/etzvdZA5JYPLoNIsiVEoFkyb+KDE6PYlnvlBCcryNmx5dw87DRwDwdHlZ7nSxcEJWwCZ2UUqFFk38USRveDJPf6EEW4xwwyNr2OVuYkNlPY1tHh3fVyqKaOKPMmMzU3j6trl4vYYb/rKGZav3YosRzhkfnfMZKxWNNPFHoaIRqTx561xaO7t4eeMBZuUPY2hidM9prFQ00cQfpSaOHsqTt84hc0gCV87MtTocpVQQ9asfv4osU3LTWfvdxXpTV6koo1f8UU6TvlLRRxO/UkpFGU38SikVZTTxK6VUlNHEr5RSUUYTv1JKRRlN/EopFWU08SulVJQRY4zVMSAiRwCn1XEMQhrQYHUQg6DxWycTqLY6iEEI5397CP/4i4wx/e6nHipP7jqNMbOsDmKgRORhY8ztVscxUBq/dUSkTM9960RC/APZTod6/ONVqwMYJI1fDVS4/9tHZfyhMtQT1lc9Sg2UnvvKCqFyxT+gP1eUigB67qugC4krfqWUUsETKlf8YUFEckXkZRHZKSK7ROQhEUkQkfNE5CMR+dj330VWx3oip4h/johs9H1tEpHLrY71RE4W/zHvjxGRJhH5lpVxRio9/63j73NfE38fiYgALwL/MMYUAUVAEvBLusvxLjHGnAF8FnjSskBPopf4twCzjDHTgCXAn0UkVCq+gF7j7/Fb4E0Lwot4ev5bJyDnvjEmqF9ALvAysBPYBTwEJAAZgB1oAh4Kdlx9iHsxsOK4ZUOBOmDIMcsEqAUSrI55gPGPBQ4DsVbH3J/4gcuAXwE/Ar5ldbwn+RnC8tzv5/mj53+QYx/IuR/UK/5efnO1Ad8HQvXP9EnAR8cuMMY0AnuAwmMWXwmsN8a0By+0Pjll/CIyV0S2Ah8DXzLGeIIf4imdKv5pwN3AvUGPqo/C/NwHPf+t5PdzP9hDPYuANmPMXwGMMV3AN4Cb6b7RvJLuD0FYEpFJwH3AF62Opb+MMWuMMZOA2cB3RCTR6pj64UfA/caYJqsDOYWIPvdBz3+L/IgBnPvBTvx9vWoIRduAmccuEJGhwEjAKSK5wEvAzcaYCgvi680p4+9ZZozZTveQw+SgRte7U8WfBvxSRPYAXwe+KyJfDXaAvQjncx/0/LeS3899vbnbd+8CySJyM4CI2IDf8P/jtK8D9xhjPrAuxFM6Vfwje25miUg+UEx3QgolJ43fGDPbGFNgjCkAHgD+2xjzkGWRRiY9/63j93M/2Im/T791Q5HpvqNyOXCViOwEagCvMeZnwFfpvmr7wTFlYdkWhvsJvcR/NrBJRDbSfdX2FWNMSDUO6yX+cBC25z7o+W+lgJz7Qb47LUAZ3X8OAtiAvwD/dcw6txCilQ3H/SxnAnuBGVbHovFbH08f4o2Ycz8c//0jKX5/xB70J3dFJA/4A3A6kAU8Z4z5ou+9PXSXKcUD9cD5xphtQQ1QqQDRc1+FCktbNojImcAzwOXGmPWWBaJUkOm5r6ykvXqUUirKaFWPUkpFmYAkfhHJExG7iGwTka0i8jXf8uEi8i9fo6F/icgw3/JiEVklIu3HNxkSkXQReUFEHCKyXUTmBSJmpfzBX+e+iEw4pkJmo4g0isjXLfqxVIQJyFCPiIwCRhlj1otIKt0PrlxGd9VCrTHmFyJyDzDMGHO3r/Qr37dOnTHm18fs63HgfWPMIyISDyQbY+r9HrRSfuDPc/+YfdqA/cBcY8ze4PwkKpIF5IrfGHOw54aVMeYIsB3IAS4FHvet9jjdJzvGGJcxZh3Qeex+RCQNmA886luvQ5O+CmX+OvePsxio0KSv/CXgY/wiUgBMB9YAI4wxB31vHQJG9LL5WMAN/FVENojIIyKSErBglfKjQZ77x7qO7gogpfwioIlfRIYAfwe+brr7khxluseYehtnigVmAH80xkwHmoF7AhGrUv7kh3O/Zz/xwGeAv/k9SBW1Apb4RSSO7hP/KWPMi77Fh31joD1joa5edlMFVBlj1vi+f4HuXwRKhSw/nfs9LqS7zfFh/0eqolWgqnqE7nH57caY3x7z1it0z9CD778vn2o/xphDQKWITPAtWkx3zxOlQpK/zv1jXI8O8yg/C1RVz9nA+3RPauD1Lf4u3WOdzwNj6O41cY0xplZERtLdx2Sob/0mYKIxplFEpgGP0P0o+y7gc8aYOr8HrZQf+PncTwH2AeOMMQ3B/UlUJNMnd5VSKsrok7tKKRVlNPErpVSU0cSvlFJRRhO/UkpFGU38SikVZTTxK6VUlNHEr5RSUUYTv1JKRZn/Az/HWLEmqwY8AAAAAElFTkSuQmCC\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "quarterly_revenue.plot(kind=\"line\")\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`to_timestamp`를 호출해서 기간을 타임스탬프로 변경할 수 있습니다. 기본적으로 기간의 첫 번째 날을 반환합니다. 하지만 `how`와 `freq`를 지정해서 기간의 마지막 시간을 얻을 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 47, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.268964Z", "iopub.status.busy": "2020-10-16T07:31:26.267481Z", "iopub.status.idle": "2020-10-16T07:31:26.271761Z", "shell.execute_reply": "2020-10-16T07:31:26.272657Z" } }, "outputs": [ { "data": { "text/plain": [ "2016-03-31 23:59:59.999999999 300\n", "2016-06-30 23:59:59.999999999 320\n", "2016-09-30 23:59:59.999999999 290\n", "2016-12-31 23:59:59.999999999 390\n", "2017-03-31 23:59:59.999999999 320\n", "2017-06-30 23:59:59.999999999 360\n", "2017-09-30 23:59:59.999999999 310\n", "2017-12-31 23:59:59.999999999 410\n", "dtype: int64" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "last_hours = quarterly_revenue.to_timestamp(how=\"end\", freq=\"H\")\n", "last_hours" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`to_peroid`를 호출하면 다시 기간으로 돌아갑니다:" ] }, { "cell_type": "code", "execution_count": 48, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.283017Z", "iopub.status.busy": "2020-10-16T07:31:26.281932Z", "iopub.status.idle": "2020-10-16T07:31:26.286503Z", "shell.execute_reply": "2020-10-16T07:31:26.287371Z" } }, "outputs": [ { "data": { "text/plain": [ "2016Q1 300\n", "2016Q2 320\n", "2016Q3 290\n", "2016Q4 390\n", "2017Q1 320\n", "2017Q2 360\n", "2017Q3 310\n", "2017Q4 410\n", "Freq: Q-DEC, dtype: int64" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "last_hours.to_period()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "판다스는 여러 가지 시간 관련 함수를 많이 제공합니다. [온라인 문서](http://pandas.pydata.org/pandas-docs/stable/timeseries.html)를 확인해 보세요. 예를 하나 들면 2016년 매월 마지막 업무일의 9시를 얻는 방법은 다음과 같습니다:" ] }, { "cell_type": "code", "execution_count": 49, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.302110Z", "iopub.status.busy": "2020-10-16T07:31:26.300761Z", "iopub.status.idle": "2020-10-16T07:31:26.305420Z", "shell.execute_reply": "2020-10-16T07:31:26.306523Z" } }, "outputs": [ { "data": { "text/plain": [ "PeriodIndex(['2016-01-29 09:00', '2016-02-29 09:00', '2016-03-31 09:00',\n", " '2016-04-29 09:00', '2016-05-31 09:00', '2016-06-30 09:00',\n", " '2016-07-29 09:00', '2016-08-31 09:00', '2016-09-30 09:00',\n", " '2016-10-31 09:00', '2016-11-30 09:00', '2016-12-30 09:00'],\n", " dtype='period[H]', freq='H')" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "months_2016 = pd.period_range(\"2016\", periods=12, freq=\"M\")\n", "one_day_after_last_days = months_2016.asfreq(\"D\") + 1\n", "last_bdays = one_day_after_last_days.to_timestamp() - pd.tseries.offsets.BDay()\n", "last_bdays.to_period(\"H\") + 9" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# `DataFrame` 객체\n", "\n", "데이터프레임 객체는 스프레드시트를 표현합니다. 셀 값, 열 이름, 행 인덱스 레이블을 가집니다. 다른 열을 바탕으로 열을 계산하는 식을 쓸 수 있고 피봇 테이블을 만들고, 행을 그룹핑하고, 그래프를 그릴 수 있습니다. `DataFrame`을 `Series`의 딕셔너리로 볼 수 있습니다.\n", "\n", "## `DataFrame` 만들기\n", "\n", "`Series` 객체의 딕셔너리를 전달하여 데이터프레임을 만들 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 50, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.323422Z", "iopub.status.busy": "2020-10-16T07:31:26.322071Z", "iopub.status.idle": "2020-10-16T07:31:26.329974Z", "shell.execute_reply": "2020-10-16T07:31:26.330949Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
weightbirthyearchildrenhobby
alice681985NaNBiking
bob8319843.0Dancing
charles11219920.0NaN
\n", "
" ], "text/plain": [ " weight birthyear children hobby\n", "alice 68 1985 NaN Biking\n", "bob 83 1984 3.0 Dancing\n", "charles 112 1992 0.0 NaN" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "people_dict = {\n", " \"weight\": pd.Series([68, 83, 112], index=[\"alice\", \"bob\", \"charles\"]),\n", " \"birthyear\": pd.Series([1984, 1985, 1992], index=[\"bob\", \"alice\", \"charles\"], name=\"year\"),\n", " \"children\": pd.Series([0, 3], index=[\"charles\", \"bob\"]),\n", " \"hobby\": pd.Series([\"Biking\", \"Dancing\"], index=[\"alice\", \"bob\"]),\n", "}\n", "people = pd.DataFrame(people_dict)\n", "people" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "몇가지 알아 두어야 할 것은 다음과 같습니다:\n", "\n", "* `Series`는 인덱스를 기반으로 자동으로 정렬됩니다.\n", "* 누란된 값은 `NaN`으로 표현됩니다.\n", "* `Series` 이름은 무시됩니다(`\"year\"`란 이름은 삭제됩니다).\n", "* `DataFrame`은 주피터 노트북에서 멋지게 출력됩니다!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "예상하는 방식으로 열을 참조할 수 있고 `Serires` 객체가 반환됩니다:" ] }, { "cell_type": "code", "execution_count": 51, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.337478Z", "iopub.status.busy": "2020-10-16T07:31:26.336279Z", "iopub.status.idle": "2020-10-16T07:31:26.340155Z", "shell.execute_reply": "2020-10-16T07:31:26.341062Z" } }, "outputs": [ { "data": { "text/plain": [ "alice 1985\n", "bob 1984\n", "charles 1992\n", "Name: birthyear, dtype: int64" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "people[\"birthyear\"]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "동시에 여러 개의 열을 선택할 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 52, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.358410Z", "iopub.status.busy": "2020-10-16T07:31:26.357116Z", "iopub.status.idle": "2020-10-16T07:31:26.362134Z", "shell.execute_reply": "2020-10-16T07:31:26.363233Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
birthyearhobby
alice1985Biking
bob1984Dancing
charles1992NaN
\n", "
" ], "text/plain": [ " birthyear hobby\n", "alice 1985 Biking\n", "bob 1984 Dancing\n", "charles 1992 NaN" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "people[[\"birthyear\", \"hobby\"]]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "열 리스트나 행 인덱스 레이블을 `DataFrame` 생성자에 전달하면 해당 열과 행으로 채워진 데이터프레임이 반환됩니다. 예를 들면:" ] }, { "cell_type": "code", "execution_count": 53, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.383281Z", "iopub.status.busy": "2020-10-16T07:31:26.381945Z", "iopub.status.idle": "2020-10-16T07:31:26.386650Z", "shell.execute_reply": "2020-10-16T07:31:26.387670Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
birthyearweightheight
bob1984.083.0NaN
alice1985.068.0NaN
eugeneNaNNaNNaN
\n", "
" ], "text/plain": [ " birthyear weight height\n", "bob 1984.0 83.0 NaN\n", "alice 1985.0 68.0 NaN\n", "eugene NaN NaN NaN" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d2 = pd.DataFrame(\n", " people_dict,\n", " columns=[\"birthyear\", \"weight\", \"height\"],\n", " index=[\"bob\", \"alice\", \"eugene\"]\n", " )\n", "d2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`DataFrame`을 만드는 또 다른 편리한 방법은 `ndarray`나 리스트의 리스트로 모든 값을 생성자에게 전달하고 열 이름과 행 인덱스 레이블을 각기 지정하는 것입니다:" ] }, { "cell_type": "code", "execution_count": 54, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.398021Z", "iopub.status.busy": "2020-10-16T07:31:26.396793Z", "iopub.status.idle": "2020-10-16T07:31:26.413413Z", "shell.execute_reply": "2020-10-16T07:31:26.414561Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
birthyearchildrenhobbyweight
alice1985NaNBiking68
bob19843.0Dancing83
charles19920.0NaN112
\n", "
" ], "text/plain": [ " birthyear children hobby weight\n", "alice 1985 NaN Biking 68\n", "bob 1984 3.0 Dancing 83\n", "charles 1992 0.0 NaN 112" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "values = [\n", " [1985, np.nan, \"Biking\", 68],\n", " [1984, 3, \"Dancing\", 83],\n", " [1992, 0, np.nan, 112]\n", " ]\n", "d3 = pd.DataFrame(\n", " values,\n", " columns=[\"birthyear\", \"children\", \"hobby\", \"weight\"],\n", " index=[\"alice\", \"bob\", \"charles\"]\n", " )\n", "d3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "누락된 값을 지정하려면 `np.nan`이나 넘파이 마스크 배열을 사용합니다:" ] }, { "cell_type": "code", "execution_count": 55, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.425026Z", "iopub.status.busy": "2020-10-16T07:31:26.423521Z", "iopub.status.idle": "2020-10-16T07:31:26.438112Z", "shell.execute_reply": "2020-10-16T07:31:26.439307Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
birthyearchildrenhobbyweight
alice1985NaNBiking68
bob19843Dancing83
charles19920NaN112
\n", "
" ], "text/plain": [ " birthyear children hobby weight\n", "alice 1985 NaN Biking 68\n", "bob 1984 3 Dancing 83\n", "charles 1992 0 NaN 112" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "masked_array = np.ma.asarray(values, dtype=np.object)\n", "masked_array[(0, 2), (1, 2)] = np.ma.masked\n", "d3 = pd.DataFrame(\n", " masked_array,\n", " columns=[\"birthyear\", \"children\", \"hobby\", \"weight\"],\n", " index=[\"alice\", \"bob\", \"charles\"]\n", " )\n", "d3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`ndarray` 대신에 `DataFrame` 객체를 전달할 수도 있습니다:" ] }, { "cell_type": "code", "execution_count": 56, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.450844Z", "iopub.status.busy": "2020-10-16T07:31:26.449596Z", "iopub.status.idle": "2020-10-16T07:31:26.454051Z", "shell.execute_reply": "2020-10-16T07:31:26.455073Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
hobbychildren
aliceBikingNaN
bobDancing3
\n", "
" ], "text/plain": [ " hobby children\n", "alice Biking NaN\n", "bob Dancing 3" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d4 = pd.DataFrame(\n", " d3,\n", " columns=[\"hobby\", \"children\"],\n", " index=[\"alice\", \"bob\"]\n", " )\n", "d4" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "딕셔너리의 딕셔너리(또는 리스트의 리스트)로 `DataFrame`을 만들 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 57, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.472738Z", "iopub.status.busy": "2020-10-16T07:31:26.466378Z", "iopub.status.idle": "2020-10-16T07:31:26.476045Z", "shell.execute_reply": "2020-10-16T07:31:26.477041Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
birthyearhobbyweightchildren
alice1985Biking68NaN
bob1984Dancing833.0
charles1992NaN1120.0
\n", "
" ], "text/plain": [ " birthyear hobby weight children\n", "alice 1985 Biking 68 NaN\n", "bob 1984 Dancing 83 3.0\n", "charles 1992 NaN 112 0.0" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "people = pd.DataFrame({\n", " \"birthyear\": {\"alice\":1985, \"bob\": 1984, \"charles\": 1992},\n", " \"hobby\": {\"alice\":\"Biking\", \"bob\": \"Dancing\"},\n", " \"weight\": {\"alice\":68, \"bob\": 83, \"charles\": 112},\n", " \"children\": {\"bob\": 3, \"charles\": 0}\n", "})\n", "people" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 멀티 인덱싱\n", "\n", "모든 열이 같은 크기의 튜플이면 멀티 인덱스로 인식합니다. 열 인덱스 레이블에도 같은 방식이 적용됩니다. 예를 들면:" ] }, { "cell_type": "code", "execution_count": 58, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.504047Z", "iopub.status.busy": "2020-10-16T07:31:26.502935Z", "iopub.status.idle": "2020-10-16T07:31:26.507572Z", "shell.execute_reply": "2020-10-16T07:31:26.508472Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
publicprivate
birthyearhobbyweightchildren
Parisalice1985Biking68NaN
bob1984Dancing833.0
Londoncharles1992NaN1120.0
\n", "
" ], "text/plain": [ " public private \n", " birthyear hobby weight children\n", "Paris alice 1985 Biking 68 NaN\n", " bob 1984 Dancing 83 3.0\n", "London charles 1992 NaN 112 0.0" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d5 = pd.DataFrame(\n", " {\n", " (\"public\", \"birthyear\"):\n", " {(\"Paris\",\"alice\"):1985, (\"Paris\",\"bob\"): 1984, (\"London\",\"charles\"): 1992},\n", " (\"public\", \"hobby\"):\n", " {(\"Paris\",\"alice\"):\"Biking\", (\"Paris\",\"bob\"): \"Dancing\"},\n", " (\"private\", \"weight\"):\n", " {(\"Paris\",\"alice\"):68, (\"Paris\",\"bob\"): 83, (\"London\",\"charles\"): 112},\n", " (\"private\", \"children\"):\n", " {(\"Paris\", \"alice\"):np.nan, (\"Paris\",\"bob\"): 3, (\"London\",\"charles\"): 0}\n", " }\n", ")\n", "d5" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "이제 `\"public\"` 열을 모두 담은 `DataFrame`을 손쉽게 만들 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 59, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.523804Z", "iopub.status.busy": "2020-10-16T07:31:26.522714Z", "iopub.status.idle": "2020-10-16T07:31:26.527772Z", "shell.execute_reply": "2020-10-16T07:31:26.528758Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
birthyearhobby
Parisalice1985Biking
bob1984Dancing
Londoncharles1992NaN
\n", "
" ], "text/plain": [ " birthyear hobby\n", "Paris alice 1985 Biking\n", " bob 1984 Dancing\n", "London charles 1992 NaN" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d5[\"public\"]" ] }, { "cell_type": "code", "execution_count": 60, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.539921Z", "iopub.status.busy": "2020-10-16T07:31:26.538672Z", "iopub.status.idle": "2020-10-16T07:31:26.543468Z", "shell.execute_reply": "2020-10-16T07:31:26.544424Z" } }, "outputs": [ { "data": { "text/plain": [ "Paris alice Biking\n", " bob Dancing\n", "London charles NaN\n", "Name: (public, hobby), dtype: object" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d5[\"public\", \"hobby\"] # d5[\"public\"][\"hobby\"]와 같습니다." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 레벨 낮추기\n", "\n", "`d5`를 다시 확인해 보죠:" ] }, { "cell_type": "code", "execution_count": 61, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.562331Z", "iopub.status.busy": "2020-10-16T07:31:26.560989Z", "iopub.status.idle": "2020-10-16T07:31:26.565827Z", "shell.execute_reply": "2020-10-16T07:31:26.566935Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
publicprivate
birthyearhobbyweightchildren
Parisalice1985Biking68NaN
bob1984Dancing833.0
Londoncharles1992NaN1120.0
\n", "
" ], "text/plain": [ " public private \n", " birthyear hobby weight children\n", "Paris alice 1985 Biking 68 NaN\n", " bob 1984 Dancing 83 3.0\n", "London charles 1992 NaN 112 0.0" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d5" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "열의 레벨(level)이 2개이고 인덱스 레벨이 2개입니다. `droplevel()`을 사용해 열 레벨을 낮출 수 있습니다(인덱스도 마찬가지입니다):" ] }, { "cell_type": "code", "execution_count": 62, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.584582Z", "iopub.status.busy": "2020-10-16T07:31:26.583237Z", "iopub.status.idle": "2020-10-16T07:31:26.587765Z", "shell.execute_reply": "2020-10-16T07:31:26.588935Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
birthyearhobbyweightchildren
Parisalice1985Biking68NaN
bob1984Dancing833.0
Londoncharles1992NaN1120.0
\n", "
" ], "text/plain": [ " birthyear hobby weight children\n", "Paris alice 1985 Biking 68 NaN\n", " bob 1984 Dancing 83 3.0\n", "London charles 1992 NaN 112 0.0" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d5.columns = d5.columns.droplevel(level = 0)\n", "d5" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 전치\n", "\n", "`T` 속성을 사용해 열과 인덱스를 바꿀 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 63, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.608084Z", "iopub.status.busy": "2020-10-16T07:31:26.606912Z", "iopub.status.idle": "2020-10-16T07:31:26.611322Z", "shell.execute_reply": "2020-10-16T07:31:26.612358Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
ParisLondon
alicebobcharles
birthyear198519841992
hobbyBikingDancingNaN
weight6883112
childrenNaN30
\n", "
" ], "text/plain": [ " Paris London\n", " alice bob charles\n", "birthyear 1985 1984 1992\n", "hobby Biking Dancing NaN\n", "weight 68 83 112\n", "children NaN 3 0" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d6 = d5.T\n", "d6" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 레벨 스택과 언스택\n", "\n", "`stack()` 메서드는 가장 낮은 열 레벨을 가장 낮은 인덱스 뒤에 추가합니다:" ] }, { "cell_type": "code", "execution_count": 64, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.620480Z", "iopub.status.busy": "2020-10-16T07:31:26.619233Z", "iopub.status.idle": "2020-10-16T07:31:26.645121Z", "shell.execute_reply": "2020-10-16T07:31:26.645952Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
LondonParis
birthyearaliceNaN1985
bobNaN1984
charles1992NaN
hobbyaliceNaNBiking
bobNaNDancing
weightaliceNaN68
bobNaN83
charles112NaN
childrenbobNaN3
charles0NaN
\n", "
" ], "text/plain": [ " London Paris\n", "birthyear alice NaN 1985\n", " bob NaN 1984\n", " charles 1992 NaN\n", "hobby alice NaN Biking\n", " bob NaN Dancing\n", "weight alice NaN 68\n", " bob NaN 83\n", " charles 112 NaN\n", "children bob NaN 3\n", " charles 0 NaN" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d7 = d6.stack()\n", "d7" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`NaN` 값이 생겼습니다. 이전에 없던 조합이 생겼기 때문입니다(예를 들어 `London`에 `bob`이 없었습니다).\n", "\n", "`unstack()`을 호출하면 반대가 됩니다. 여기에서도 많은 `NaN` 값이 생성됩니다." ] }, { "cell_type": "code", "execution_count": 65, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.670564Z", "iopub.status.busy": "2020-10-16T07:31:26.669099Z", "iopub.status.idle": "2020-10-16T07:31:26.674498Z", "shell.execute_reply": "2020-10-16T07:31:26.675704Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
LondonParis
alicebobcharlesalicebobcharles
birthyearNaNNaN199219851984NaN
childrenNaNNaN0NaN3NaN
hobbyNaNNaNNaNBikingDancingNaN
weightNaNNaN1126883NaN
\n", "
" ], "text/plain": [ " London Paris \n", " alice bob charles alice bob charles\n", "birthyear NaN NaN 1992 1985 1984 NaN\n", "children NaN NaN 0 NaN 3 NaN\n", "hobby NaN NaN NaN Biking Dancing NaN\n", "weight NaN NaN 112 68 83 NaN" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d8 = d7.unstack()\n", "d8" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`unstack`을 다시 호출하면 `Series` 객체가 만들어 집니다:" ] }, { "cell_type": "code", "execution_count": 66, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.690137Z", "iopub.status.busy": "2020-10-16T07:31:26.688874Z", "iopub.status.idle": "2020-10-16T07:31:26.693084Z", "shell.execute_reply": "2020-10-16T07:31:26.694056Z" } }, "outputs": [ { "data": { "text/plain": [ "London alice birthyear NaN\n", " children NaN\n", " hobby NaN\n", " weight NaN\n", " bob birthyear NaN\n", " children NaN\n", " hobby NaN\n", " weight NaN\n", " charles birthyear 1992\n", " children 0\n", " hobby NaN\n", " weight 112\n", "Paris alice birthyear 1985\n", " children NaN\n", " hobby Biking\n", " weight 68\n", " bob birthyear 1984\n", " children 3\n", " hobby Dancing\n", " weight 83\n", " charles birthyear NaN\n", " children NaN\n", " hobby NaN\n", " weight NaN\n", "dtype: object" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d9 = d8.unstack()\n", "d9" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`stack()`과 `unstack()` 메서드를 사용할 때 스택/언스택할 `level`을 선택할 수 있습니다. 심지어 한 번에 여러 개의 레벨을 스택/언스택할 수도 있습니다:" ] }, { "cell_type": "code", "execution_count": 67, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.719311Z", "iopub.status.busy": "2020-10-16T07:31:26.718139Z", "iopub.status.idle": "2020-10-16T07:31:26.723311Z", "shell.execute_reply": "2020-10-16T07:31:26.724247Z" }, "scrolled": true }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
LondonParis
alicebobcharlesalicebobcharles
birthyearNaNNaN199219851984NaN
childrenNaNNaN0NaN3NaN
hobbyNaNNaNNaNBikingDancingNaN
weightNaNNaN1126883NaN
\n", "
" ], "text/plain": [ " London Paris \n", " alice bob charles alice bob charles\n", "birthyear NaN NaN 1992 1985 1984 NaN\n", "children NaN NaN 0 NaN 3 NaN\n", "hobby NaN NaN NaN Biking Dancing NaN\n", "weight NaN NaN 112 68 83 NaN" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d10 = d9.unstack(level = (0,1))\n", "d10" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 대부분의 메서드는 수정된 복사본을 반환합니다\n", "\n", "눈치챘겠지만 `stack()`과 `unstack()` 메서드는 객체를 수정하지 않습니다. 대신 복사본을 만들어 반환합니다. 판다스에 있는 대부분의 메서드들이 이렇게 동작합니다." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 행 참조하기\n", "\n", "`people` `DataFrame`으로 돌아가 보죠:" ] }, { "cell_type": "code", "execution_count": 68, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.740196Z", "iopub.status.busy": "2020-10-16T07:31:26.739030Z", "iopub.status.idle": "2020-10-16T07:31:26.743455Z", "shell.execute_reply": "2020-10-16T07:31:26.744486Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
birthyearhobbyweightchildren
alice1985Biking68NaN
bob1984Dancing833.0
charles1992NaN1120.0
\n", "
" ], "text/plain": [ " birthyear hobby weight children\n", "alice 1985 Biking 68 NaN\n", "bob 1984 Dancing 83 3.0\n", "charles 1992 NaN 112 0.0" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "people" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`loc` 속성으로 열 대신 행을 참조할 수 있습니다. `DataFrame`의 열 이름이 행 인덱스 레이블로 매핑된 `Series` 객체가 반환됩니다:" ] }, { "cell_type": "code", "execution_count": 69, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.753868Z", "iopub.status.busy": "2020-10-16T07:31:26.752625Z", "iopub.status.idle": "2020-10-16T07:31:26.756975Z", "shell.execute_reply": "2020-10-16T07:31:26.757905Z" } }, "outputs": [ { "data": { "text/plain": [ "birthyear 1992\n", "hobby NaN\n", "weight 112\n", "children 0\n", "Name: charles, dtype: object" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "people.loc[\"charles\"]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`iloc` 속성을 사용해 정수 인덱스로 행을 참조할 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 70, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.767760Z", "iopub.status.busy": "2020-10-16T07:31:26.766655Z", "iopub.status.idle": "2020-10-16T07:31:26.771119Z", "shell.execute_reply": "2020-10-16T07:31:26.772031Z" } }, "outputs": [ { "data": { "text/plain": [ "birthyear 1992\n", "hobby NaN\n", "weight 112\n", "children 0\n", "Name: charles, dtype: object" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "people.iloc[2]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "행을 슬라이싱할 수 있으며 `DataFrame` 객체가 반환됩니다:" ] }, { "cell_type": "code", "execution_count": 71, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.786461Z", "iopub.status.busy": "2020-10-16T07:31:26.785104Z", "iopub.status.idle": "2020-10-16T07:31:26.789947Z", "shell.execute_reply": "2020-10-16T07:31:26.791052Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
birthyearhobbyweightchildren
bob1984Dancing833.0
charles1992NaN1120.0
\n", "
" ], "text/plain": [ " birthyear hobby weight children\n", "bob 1984 Dancing 83 3.0\n", "charles 1992 NaN 112 0.0" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "people.iloc[1:3]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "마자믹으로 불리언 배열을 전달하여 해당하는 행을 가져올 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 72, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.808646Z", "iopub.status.busy": "2020-10-16T07:31:26.807301Z", "iopub.status.idle": "2020-10-16T07:31:26.811968Z", "shell.execute_reply": "2020-10-16T07:31:26.813013Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
birthyearhobbyweightchildren
alice1985Biking68NaN
charles1992NaN1120.0
\n", "
" ], "text/plain": [ " birthyear hobby weight children\n", "alice 1985 Biking 68 NaN\n", "charles 1992 NaN 112 0.0" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "people[np.array([True, False, True])]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "불리언 표현식을 사용할 때 아주 유용합니다:" ] }, { "cell_type": "code", "execution_count": 73, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.829832Z", "iopub.status.busy": "2020-10-16T07:31:26.828532Z", "iopub.status.idle": "2020-10-16T07:31:26.833273Z", "shell.execute_reply": "2020-10-16T07:31:26.834311Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
birthyearhobbyweightchildren
alice1985Biking68NaN
bob1984Dancing833.0
\n", "
" ], "text/plain": [ " birthyear hobby weight children\n", "alice 1985 Biking 68 NaN\n", "bob 1984 Dancing 83 3.0" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "people[people[\"birthyear\"] < 1990]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 열 추가, 삭제\n", "\n", "`DataFrame`을 `Series`의 딕셔너리처럼 다룰 수 있습니다. 따라서 다음 같이 쓸 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 74, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.848712Z", "iopub.status.busy": "2020-10-16T07:31:26.847466Z", "iopub.status.idle": "2020-10-16T07:31:26.852951Z", "shell.execute_reply": "2020-10-16T07:31:26.851924Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
birthyearhobbyweightchildren
alice1985Biking68NaN
bob1984Dancing833.0
charles1992NaN1120.0
\n", "
" ], "text/plain": [ " birthyear hobby weight children\n", "alice 1985 Biking 68 NaN\n", "bob 1984 Dancing 83 3.0\n", "charles 1992 NaN 112 0.0" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "people" ] }, { "cell_type": "code", "execution_count": 75, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.873305Z", "iopub.status.busy": "2020-10-16T07:31:26.872037Z", "iopub.status.idle": "2020-10-16T07:31:26.876795Z", "shell.execute_reply": "2020-10-16T07:31:26.877922Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
hobbyweightageover 30
aliceBiking6833True
bobDancing8334True
charlesNaN11226False
\n", "
" ], "text/plain": [ " hobby weight age over 30\n", "alice Biking 68 33 True\n", "bob Dancing 83 34 True\n", "charles NaN 112 26 False" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "people[\"age\"] = 2018 - people[\"birthyear\"] # \"age\" 열을 추가합니다\n", "people[\"over 30\"] = people[\"age\"] > 30 # \"over 30\" 열을 추가합니다\n", "birthyears = people.pop(\"birthyear\")\n", "del people[\"children\"]\n", "\n", "people" ] }, { "cell_type": "code", "execution_count": 76, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.886529Z", "iopub.status.busy": "2020-10-16T07:31:26.885421Z", "iopub.status.idle": "2020-10-16T07:31:26.890520Z", "shell.execute_reply": "2020-10-16T07:31:26.889567Z" } }, "outputs": [ { "data": { "text/plain": [ "alice 1985\n", "bob 1984\n", "charles 1992\n", "Name: birthyear, dtype: int64" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "birthyears" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "새로운 열을 추가할 때 행의 개수는 같아야 합니다. 누락된 행은 `NaN`으로 채워지고 추가적인 행은 무시됩니다:" ] }, { "cell_type": "code", "execution_count": 77, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.910981Z", "iopub.status.busy": "2020-10-16T07:31:26.909610Z", "iopub.status.idle": "2020-10-16T07:31:26.914677Z", "shell.execute_reply": "2020-10-16T07:31:26.915783Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
hobbyweightageover 30pets
aliceBiking6833TrueNaN
bobDancing8334True0.0
charlesNaN11226False5.0
\n", "
" ], "text/plain": [ " hobby weight age over 30 pets\n", "alice Biking 68 33 True NaN\n", "bob Dancing 83 34 True 0.0\n", "charles NaN 112 26 False 5.0" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "people[\"pets\"] = pd.Series({\"bob\": 0, \"charles\": 5, \"eugene\":1}) # alice 누락됨, eugene은 무시됨\n", "people" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "새로운 열을 추가할 때 기본적으로 (오른쪽) 끝에 추가됩니다. `insert()` 메서드를 사용해 다른 곳에 열을 추가할 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 78, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.935076Z", "iopub.status.busy": "2020-10-16T07:31:26.933817Z", "iopub.status.idle": "2020-10-16T07:31:26.938345Z", "shell.execute_reply": "2020-10-16T07:31:26.939377Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
hobbyheightweightageover 30pets
aliceBiking1726833TrueNaN
bobDancing1818334True0.0
charlesNaN18511226False5.0
\n", "
" ], "text/plain": [ " hobby height weight age over 30 pets\n", "alice Biking 172 68 33 True NaN\n", "bob Dancing 181 83 34 True 0.0\n", "charles NaN 185 112 26 False 5.0" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "people.insert(1, \"height\", [172, 181, 185])\n", "people" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 새로운 열 할당하기\n", "\n", "`assign()` 메서드를 호출하여 새로운 열을 만들 수도 있습니다. 이는 새로운 `DataFrame` 객체를 반환하며 원본 객체는 변경되지 않습니다:" ] }, { "cell_type": "code", "execution_count": 79, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.963676Z", "iopub.status.busy": "2020-10-16T07:31:26.962421Z", "iopub.status.idle": "2020-10-16T07:31:26.966980Z", "shell.execute_reply": "2020-10-16T07:31:26.968012Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
hobbyheightweightageover 30petsbody_mass_indexhas_pets
aliceBiking1726833TrueNaN22.985398False
bobDancing1818334True0.025.335002False
charlesNaN18511226False5.032.724617True
\n", "
" ], "text/plain": [ " hobby height weight age over 30 pets body_mass_index \\\n", "alice Biking 172 68 33 True NaN 22.985398 \n", "bob Dancing 181 83 34 True 0.0 25.335002 \n", "charles NaN 185 112 26 False 5.0 32.724617 \n", "\n", " has_pets \n", "alice False \n", "bob False \n", "charles True " ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "people.assign(\n", " body_mass_index = people[\"weight\"] / (people[\"height\"] / 100) ** 2,\n", " has_pets = people[\"pets\"] > 0\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "할당문 안에서 만든 열은 접근할 수 없습니다:" ] }, { "cell_type": "code", "execution_count": 80, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:26.979950Z", "iopub.status.busy": "2020-10-16T07:31:26.978686Z", "iopub.status.idle": "2020-10-16T07:31:26.984376Z", "shell.execute_reply": "2020-10-16T07:31:26.983363Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "키 에러: 'body_mass_index'\n" ] } ], "source": [ "try:\n", " people.assign(\n", " body_mass_index = people[\"weight\"] / (people[\"height\"] / 100) ** 2,\n", " overweight = people[\"body_mass_index\"] > 25\n", " )\n", "except KeyError as e:\n", " print(\"키 에러:\", e)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "해결책은 두 개의 연속된 할당문으로 나누는 것입니다:" ] }, { "cell_type": "code", "execution_count": 81, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:27.008299Z", "iopub.status.busy": "2020-10-16T07:31:26.995147Z", "iopub.status.idle": "2020-10-16T07:31:27.014321Z", "shell.execute_reply": "2020-10-16T07:31:27.012947Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
hobbyheightweightageover 30petsbody_mass_indexoverweight
aliceBiking1726833TrueNaN22.985398False
bobDancing1818334True0.025.335002True
charlesNaN18511226False5.032.724617True
\n", "
" ], "text/plain": [ " hobby height weight age over 30 pets body_mass_index \\\n", "alice Biking 172 68 33 True NaN 22.985398 \n", "bob Dancing 181 83 34 True 0.0 25.335002 \n", "charles NaN 185 112 26 False 5.0 32.724617 \n", "\n", " overweight \n", "alice False \n", "bob True \n", "charles True " ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d6 = people.assign(body_mass_index = people[\"weight\"] / (people[\"height\"] / 100) ** 2)\n", "d6.assign(overweight = d6[\"body_mass_index\"] > 25)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "임시 변수 `d6`를 만들면 불편합니다. `assign()` 메서드를 연결하고 싶겠지만 `people` 객체가 첫 번째 할당문에서 실제로 수정되지 않기 때문에 작동하지 않습니다:" ] }, { "cell_type": "code", "execution_count": 82, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:27.029304Z", "iopub.status.busy": "2020-10-16T07:31:27.027741Z", "iopub.status.idle": "2020-10-16T07:31:27.032521Z", "shell.execute_reply": "2020-10-16T07:31:27.033510Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "키 에러: 'body_mass_index'\n" ] } ], "source": [ "try:\n", " (people\n", " .assign(body_mass_index = people[\"weight\"] / (people[\"height\"] / 100) ** 2)\n", " .assign(overweight = people[\"body_mass_index\"] > 25)\n", " )\n", "except KeyError as e:\n", " print(\"키 에러:\", e)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "하지만 걱정하지 마세요. 간단한 방법이 있습니다. `assign()` 메서드에 함수(전형적으로 `lambda` 함수)를 전달하면 `DataFrame`을 매개변수로 이 함수를 호출할 것입니다:" ] }, { "cell_type": "code", "execution_count": 83, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:27.057521Z", "iopub.status.busy": "2020-10-16T07:31:27.043525Z", "iopub.status.idle": "2020-10-16T07:31:27.062274Z", "shell.execute_reply": "2020-10-16T07:31:27.063582Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
hobbyheightweightageover 30petsbody_mass_indexoverweight
aliceBiking1726833TrueNaN22.985398False
bobDancing1818334True0.025.335002True
charlesNaN18511226False5.032.724617True
\n", "
" ], "text/plain": [ " hobby height weight age over 30 pets body_mass_index \\\n", "alice Biking 172 68 33 True NaN 22.985398 \n", "bob Dancing 181 83 34 True 0.0 25.335002 \n", "charles NaN 185 112 26 False 5.0 32.724617 \n", "\n", " overweight \n", "alice False \n", "bob True \n", "charles True " ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "(people\n", " .assign(body_mass_index = lambda df: df[\"weight\"] / (df[\"height\"] / 100) ** 2)\n", " .assign(overweight = lambda df: df[\"body_mass_index\"] > 25)\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "문제가 해결되었군요!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 표현식 평가\n", "\n", "판다스가 제공하는 뛰어난 기능 하나는 표현식 평가입니다. 이는 `numexpr` 라이브러리에 의존하기 때문에 설치가 되어 있어야 합니다." ] }, { "cell_type": "code", "execution_count": 84, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:27.088939Z", "iopub.status.busy": "2020-10-16T07:31:27.087317Z", "iopub.status.idle": "2020-10-16T07:31:27.092870Z", "shell.execute_reply": "2020-10-16T07:31:27.094182Z" } }, "outputs": [ { "data": { "text/plain": [ "alice False\n", "bob True\n", "charles True\n", "dtype: bool" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "people.eval(\"weight / (height/100) ** 2 > 25\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "할당 표현식도 지원됩니다. `inplace=True`로 지정하면 수정된 복사본을 만들지 않고 바로 `DataFrame`을 변경합니다:" ] }, { "cell_type": "code", "execution_count": 85, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:27.121360Z", "iopub.status.busy": "2020-10-16T07:31:27.119766Z", "iopub.status.idle": "2020-10-16T07:31:27.124873Z", "shell.execute_reply": "2020-10-16T07:31:27.125987Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
hobbyheightweightageover 30petsbody_mass_index
aliceBiking1726833TrueNaN22.985398
bobDancing1818334True0.025.335002
charlesNaN18511226False5.032.724617
\n", "
" ], "text/plain": [ " hobby height weight age over 30 pets body_mass_index\n", "alice Biking 172 68 33 True NaN 22.985398\n", "bob Dancing 181 83 34 True 0.0 25.335002\n", "charles NaN 185 112 26 False 5.0 32.724617" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "people.eval(\"body_mass_index = weight / (height/100) ** 2\", inplace=True)\n", "people" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`'@'`를 접두어로 사용하여 지역 변수나 전역 변수를 참조할 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 86, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:27.151724Z", "iopub.status.busy": "2020-10-16T07:31:27.150378Z", "iopub.status.idle": "2020-10-16T07:31:27.155345Z", "shell.execute_reply": "2020-10-16T07:31:27.156398Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
hobbyheightweightageover 30petsbody_mass_indexoverweight
aliceBiking1726833TrueNaN22.985398False
bobDancing1818334True0.025.335002False
charlesNaN18511226False5.032.724617True
\n", "
" ], "text/plain": [ " hobby height weight age over 30 pets body_mass_index \\\n", "alice Biking 172 68 33 True NaN 22.985398 \n", "bob Dancing 181 83 34 True 0.0 25.335002 \n", "charles NaN 185 112 26 False 5.0 32.724617 \n", "\n", " overweight \n", "alice False \n", "bob False \n", "charles True " ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "overweight_threshold = 30\n", "people.eval(\"overweight = body_mass_index > @overweight_threshold\", inplace=True)\n", "people" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## `DataFrame` 쿼리하기\n", "\n", "`query()` 메서드를 사용하면 쿼리 표현식에 기반하여 `DataFrame`을 필터링할 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 87, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:27.180483Z", "iopub.status.busy": "2020-10-16T07:31:27.168045Z", "iopub.status.idle": "2020-10-16T07:31:27.185677Z", "shell.execute_reply": "2020-10-16T07:31:27.186843Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
hobbyheightweightageover 30petsbody_mass_indexoverweight
bobDancing1818334True0.025.335002False
\n", "
" ], "text/plain": [ " hobby height weight age over 30 pets body_mass_index overweight\n", "bob Dancing 181 83 34 True 0.0 25.335002 False" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "people.query(\"age > 30 and pets == 0\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## `DataFrame` 정렬\n", "\n", "`sort_index` 메서드를 호출하여 `DataFrame`을 정렬할 수 있습니다. 기본적으로 인덱스 레이블을 기준으로 오름차순으로 행을 정렬합니다. 여기에서는 내림차순으로 정렬해 보죠:" ] }, { "cell_type": "code", "execution_count": 88, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:27.209165Z", "iopub.status.busy": "2020-10-16T07:31:27.207658Z", "iopub.status.idle": "2020-10-16T07:31:27.212703Z", "shell.execute_reply": "2020-10-16T07:31:27.213844Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
hobbyheightweightageover 30petsbody_mass_indexoverweight
charlesNaN18511226False5.032.724617True
bobDancing1818334True0.025.335002False
aliceBiking1726833TrueNaN22.985398False
\n", "
" ], "text/plain": [ " hobby height weight age over 30 pets body_mass_index \\\n", "charles NaN 185 112 26 False 5.0 32.724617 \n", "bob Dancing 181 83 34 True 0.0 25.335002 \n", "alice Biking 172 68 33 True NaN 22.985398 \n", "\n", " overweight \n", "charles True \n", "bob False \n", "alice False " ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "people.sort_index(ascending=False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`sort_index`는 `DataFrame`의 정렬된 *복사본*을 반환합니다. `people`을 직접 수정하려면 `inplace` 매개변수를 `True`로 지정합니다. 또한 `axis=1`로 지정하여 열 대신 행을 정렬할 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 89, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:27.235840Z", "iopub.status.busy": "2020-10-16T07:31:27.234491Z", "iopub.status.idle": "2020-10-16T07:31:27.239396Z", "shell.execute_reply": "2020-10-16T07:31:27.240434Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
agebody_mass_indexheighthobbyover 30overweightpetsweight
alice3322.985398172BikingTrueFalseNaN68
bob3425.335002181DancingTrueFalse0.083
charles2632.724617185NaNFalseTrue5.0112
\n", "
" ], "text/plain": [ " age body_mass_index height hobby over 30 overweight pets \\\n", "alice 33 22.985398 172 Biking True False NaN \n", "bob 34 25.335002 181 Dancing True False 0.0 \n", "charles 26 32.724617 185 NaN False True 5.0 \n", "\n", " weight \n", "alice 68 \n", "bob 83 \n", "charles 112 " ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "people.sort_index(axis=1, inplace=True)\n", "people" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "레이블이 아니라 값을 기준으로 `DataFrame`을 정렬하려면 `sort_values`에 정렬하려는 열을 지정합니다:" ] }, { "cell_type": "code", "execution_count": 90, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:27.261726Z", "iopub.status.busy": "2020-10-16T07:31:27.260351Z", "iopub.status.idle": "2020-10-16T07:31:27.265293Z", "shell.execute_reply": "2020-10-16T07:31:27.266432Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
agebody_mass_indexheighthobbyover 30overweightpetsweight
charles2632.724617185NaNFalseTrue5.0112
alice3322.985398172BikingTrueFalseNaN68
bob3425.335002181DancingTrueFalse0.083
\n", "
" ], "text/plain": [ " age body_mass_index height hobby over 30 overweight pets \\\n", "charles 26 32.724617 185 NaN False True 5.0 \n", "alice 33 22.985398 172 Biking True False NaN \n", "bob 34 25.335002 181 Dancing True False 0.0 \n", "\n", " weight \n", "charles 112 \n", "alice 68 \n", "bob 83 " ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "people.sort_values(by=\"age\", inplace=True)\n", "people" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## `DataFrame` 그래프 그리기\n", "\n", "`Series`와 마찬가지로 판다스는 `DataFrame` 기반으로 멋진 그래프를 손쉽게 그릴 수 있습니다.\n", "\n", "예를 들어 `plot` 메서드를 호출하여 `DataFrame`의 데이터에서 선 그래프를 쉽게 그릴 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 91, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:27.304606Z", "iopub.status.busy": "2020-10-16T07:31:27.301491Z", "iopub.status.idle": "2020-10-16T07:31:27.517164Z", "shell.execute_reply": "2020-10-16T07:31:27.518611Z" } }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "people.plot(kind = \"line\", x = \"body_mass_index\", y = [\"height\", \"weight\"])\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "맷플롯립의 함수가 지원하는 다른 매개변수를 사용할 수 있습니다. 예를 들어, 산점도를 그릴 때 맷플롯립의 `scatter()` 함수의 `s` 매개변수를 사용해 크기를 지정할 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 92, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:27.558226Z", "iopub.status.busy": "2020-10-16T07:31:27.556557Z", "iopub.status.idle": "2020-10-16T07:31:27.738758Z", "shell.execute_reply": "2020-10-16T07:31:27.737322Z" }, "scrolled": true }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "people.plot(kind = \"scatter\", x = \"height\", y = \"weight\", s=[40, 120, 200])\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "선택할 수 있는 옵션이 많습니다. 판다스 문서의 [시각화](http://pandas.pydata.org/pandas-docs/stable/visualization.html) 페이지에서 마음에 드는 그래프를 찾아 예제 코드를 살펴 보세요." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## `DataFrame` 연산\n", "\n", "`DataFrame`이 넘파이 배열을 흉내내려는 것은 아니지만 몇 가지 비슷한 점이 있습니다. 예제 `DataFrame`을 만들어 보죠:" ] }, { "cell_type": "code", "execution_count": 93, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:27.757668Z", "iopub.status.busy": "2020-10-16T07:31:27.756294Z", "iopub.status.idle": "2020-10-16T07:31:27.761443Z", "shell.execute_reply": "2020-10-16T07:31:27.762642Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
sepoctnov
alice889
bob1099
charles482
darwin91010
\n", "
" ], "text/plain": [ " sep oct nov\n", "alice 8 8 9\n", "bob 10 9 9\n", "charles 4 8 2\n", "darwin 9 10 10" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "grades_array = np.array([[8,8,9],[10,9,9],[4, 8, 2], [9, 10, 10]])\n", "grades = pd.DataFrame(grades_array, columns=[\"sep\", \"oct\", \"nov\"], index=[\"alice\",\"bob\",\"charles\",\"darwin\"])\n", "grades" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`DataFrame`에 넘파이 수학 함수를 적용하면 모든 값에 이 함수가 적용됩니다:" ] }, { "cell_type": "code", "execution_count": 94, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:27.780212Z", "iopub.status.busy": "2020-10-16T07:31:27.778767Z", "iopub.status.idle": "2020-10-16T07:31:27.783503Z", "shell.execute_reply": "2020-10-16T07:31:27.784467Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
sepoctnov
alice2.8284272.8284273.000000
bob3.1622783.0000003.000000
charles2.0000002.8284271.414214
darwin3.0000003.1622783.162278
\n", "
" ], "text/plain": [ " sep oct nov\n", "alice 2.828427 2.828427 3.000000\n", "bob 3.162278 3.000000 3.000000\n", "charles 2.000000 2.828427 1.414214\n", "darwin 3.000000 3.162278 3.162278" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.sqrt(grades)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "비슷하게 `DataFrame`에 하나의 값을 더하면 `DataFrame`의 모든 원소에 이 값이 더해집니다. 이를 *브로드캐스팅*이라고 합니다:" ] }, { "cell_type": "code", "execution_count": 95, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:27.798080Z", "iopub.status.busy": "2020-10-16T07:31:27.796749Z", "iopub.status.idle": "2020-10-16T07:31:27.801579Z", "shell.execute_reply": "2020-10-16T07:31:27.802616Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
sepoctnov
alice9910
bob111010
charles593
darwin101111
\n", "
" ], "text/plain": [ " sep oct nov\n", "alice 9 9 10\n", "bob 11 10 10\n", "charles 5 9 3\n", "darwin 10 11 11" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "grades + 1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "물론 산술 연산(`*`,`/`,`**`...)과 조건 연산(`>`, `==`...)을 포함해 모든 이항 연산에도 마찬가지 입니다:" ] }, { "cell_type": "code", "execution_count": 96, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:27.817148Z", "iopub.status.busy": "2020-10-16T07:31:27.815851Z", "iopub.status.idle": "2020-10-16T07:31:27.820194Z", "shell.execute_reply": "2020-10-16T07:31:27.821180Z" }, "scrolled": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
sepoctnov
aliceTrueTrueTrue
bobTrueTrueTrue
charlesFalseTrueFalse
darwinTrueTrueTrue
\n", "
" ], "text/plain": [ " sep oct nov\n", "alice True True True\n", "bob True True True\n", "charles False True False\n", "darwin True True True" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "grades >= 5" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`DataFrame`의 `max`, `sum`, `mean` 같은 집계 연산은 각 열에 적용되어 `Series` 객체가 반환됩니다:" ] }, { "cell_type": "code", "execution_count": 97, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:27.831044Z", "iopub.status.busy": "2020-10-16T07:31:27.829879Z", "iopub.status.idle": "2020-10-16T07:31:27.835347Z", "shell.execute_reply": "2020-10-16T07:31:27.834398Z" } }, "outputs": [ { "data": { "text/plain": [ "sep 7.75\n", "oct 8.75\n", "nov 7.50\n", "dtype: float64" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "grades.mean()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`all` 메서드도 집계 연산입니다: 모든 값이 `True`인지 아닌지 확인합니다. 모든 학생의 점수가 `5` 이상인 월을 찾아 보죠:" ] }, { "cell_type": "code", "execution_count": 98, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:27.845808Z", "iopub.status.busy": "2020-10-16T07:31:27.844575Z", "iopub.status.idle": "2020-10-16T07:31:27.849198Z", "shell.execute_reply": "2020-10-16T07:31:27.850237Z" } }, "outputs": [ { "data": { "text/plain": [ "sep False\n", "oct True\n", "nov False\n", "dtype: bool" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "(grades > 5).all()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Most of these functions take an optional `axis` parameter which lets you specify along which axis of the `DataFrame` you want the operation executed. The default is `axis=0`, meaning that the operation is executed vertically (on each column). You can set `axis=1` to execute the operation horizontally (on each row). For example, let's find out which students had all grades greater than `5`:" ] }, { "cell_type": "code", "execution_count": 99, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:27.860089Z", "iopub.status.busy": "2020-10-16T07:31:27.858925Z", "iopub.status.idle": "2020-10-16T07:31:27.863574Z", "shell.execute_reply": "2020-10-16T07:31:27.864558Z" } }, "outputs": [ { "data": { "text/plain": [ "alice True\n", "bob True\n", "charles False\n", "darwin True\n", "dtype: bool" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "(grades > 5).all(axis = 1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`any` 메서드는 하나라도 참이면 `True`를 반환합니다. 한 번이라도 10점을 받은 사람을 찾아 보죠:" ] }, { "cell_type": "code", "execution_count": 100, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:27.875152Z", "iopub.status.busy": "2020-10-16T07:31:27.873989Z", "iopub.status.idle": "2020-10-16T07:31:27.878564Z", "shell.execute_reply": "2020-10-16T07:31:27.879476Z" } }, "outputs": [ { "data": { "text/plain": [ "alice False\n", "bob True\n", "charles False\n", "darwin True\n", "dtype: bool" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "(grades == 10).any(axis = 1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`DataFrame`에 `Series` 객체를 더하면 (또는 다른 이항 연산을 수행하면) 판다스는 `DataFrame`에 있는 모든 *행*에 이 연산을 브로드캐스팅합니다. 이는 `Series` 객체가 `DataFrame`의 행의 개수와 크기가 같을 때만 동작합니다. 예를 들어 `DataFrame`의 `mean`(`Series` 객체)을 빼보죠:" ] }, { "cell_type": "code", "execution_count": 101, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:27.896652Z", "iopub.status.busy": "2020-10-16T07:31:27.895549Z", "iopub.status.idle": "2020-10-16T07:31:27.900125Z", "shell.execute_reply": "2020-10-16T07:31:27.901252Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
sepoctnov
alice0.25-0.751.5
bob2.250.251.5
charles-3.75-0.75-5.5
darwin1.251.252.5
\n", "
" ], "text/plain": [ " sep oct nov\n", "alice 0.25 -0.75 1.5\n", "bob 2.25 0.25 1.5\n", "charles -3.75 -0.75 -5.5\n", "darwin 1.25 1.25 2.5" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "grades - grades.mean() # grades - [7.75, 8.75, 7.50] 와 동일" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "모든 9월 성적에서 `7.75`를 빼고, 10월 성적에서 `8.75`를 빼고, 11월 성적에서 `7.50`을 뺍니다. 이는 다음 `DataFrame`을 빼는 것과 같습니다:" ] }, { "cell_type": "code", "execution_count": 102, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:27.919376Z", "iopub.status.busy": "2020-10-16T07:31:27.918032Z", "iopub.status.idle": "2020-10-16T07:31:27.922814Z", "shell.execute_reply": "2020-10-16T07:31:27.923850Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
sepoctnov
alice7.758.757.5
bob7.758.757.5
charles7.758.757.5
darwin7.758.757.5
\n", "
" ], "text/plain": [ " sep oct nov\n", "alice 7.75 8.75 7.5\n", "bob 7.75 8.75 7.5\n", "charles 7.75 8.75 7.5\n", "darwin 7.75 8.75 7.5" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.DataFrame([[7.75, 8.75, 7.50]]*4, index=grades.index, columns=grades.columns)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "모든 성적의 전체 평균을 빼고 싶다면 다음과 같은 방법을 사용합니다:" ] }, { "cell_type": "code", "execution_count": 103, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:27.943417Z", "iopub.status.busy": "2020-10-16T07:31:27.942164Z", "iopub.status.idle": "2020-10-16T07:31:27.946771Z", "shell.execute_reply": "2020-10-16T07:31:27.947804Z" }, "scrolled": true }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
sepoctnov
alice0.00.01.0
bob2.01.01.0
charles-4.00.0-6.0
darwin1.02.02.0
\n", "
" ], "text/plain": [ " sep oct nov\n", "alice 0.0 0.0 1.0\n", "bob 2.0 1.0 1.0\n", "charles -4.0 0.0 -6.0\n", "darwin 1.0 2.0 2.0" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "grades - grades.values.mean() # 모든 점수에서 전체 평균(8.00)을 뺍니다" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 자동 정렬\n", "\n", "`Series`와 비슷하게 여러 개의 `DataFrame`에 대한 연산을 수행하면 판다스는 자동으로 행 인덱스 레이블로 정렬하지만 열 이름으로도 정렬할 수 있습니다. 10월부터 12월까지 보너스 포인트를 담은 `DataFrame`을 만들어 보겠습니다:" ] }, { "cell_type": "code", "execution_count": 104, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:27.967853Z", "iopub.status.busy": "2020-10-16T07:31:27.966587Z", "iopub.status.idle": "2020-10-16T07:31:27.971328Z", "shell.execute_reply": "2020-10-16T07:31:27.972440Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
octnovdec
bob0.0NaN2.0
colinNaN1.00.0
darwin0.01.00.0
charles3.03.00.0
\n", "
" ], "text/plain": [ " oct nov dec\n", "bob 0.0 NaN 2.0\n", "colin NaN 1.0 0.0\n", "darwin 0.0 1.0 0.0\n", "charles 3.0 3.0 0.0" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "bonus_array = np.array([[0,np.nan,2],[np.nan,1,0],[0, 1, 0], [3, 3, 0]])\n", "bonus_points = pd.DataFrame(bonus_array, columns=[\"oct\", \"nov\", \"dec\"], index=[\"bob\",\"colin\", \"darwin\", \"charles\"])\n", "bonus_points" ] }, { "cell_type": "code", "execution_count": 105, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:27.995052Z", "iopub.status.busy": "2020-10-16T07:31:27.993703Z", "iopub.status.idle": "2020-10-16T07:31:28.000013Z", "shell.execute_reply": "2020-10-16T07:31:28.001109Z" }, "scrolled": true }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
decnovoctsep
aliceNaNNaNNaNNaN
bobNaNNaN9.0NaN
charlesNaN5.011.0NaN
colinNaNNaNNaNNaN
darwinNaN11.010.0NaN
\n", "
" ], "text/plain": [ " dec nov oct sep\n", "alice NaN NaN NaN NaN\n", "bob NaN NaN 9.0 NaN\n", "charles NaN 5.0 11.0 NaN\n", "colin NaN NaN NaN NaN\n", "darwin NaN 11.0 10.0 NaN" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "grades + bonus_points" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "덧셈 연산이 수행되었지만 너무 많은 원소가 `NaN`이 되었습니다. `DataFrame`을 정렬할 때 일부 열과 행이 한 쪽에만 있기 때문입니다. 다른 쪽에는 누란되었다고 간주합니다(`NaN`). `NaN`에 어떤 수를 더하면 `NaN`이 됩니다.\n", "\n", "## 누락된 데이터 다루기\n", "\n", "실제 데이터에서 누락된 데이터를 다루는 경우는 자주 발생합니다. 판다스는 누락된 데이터를 다룰 수 있는 몇 가지 방법을 제공합니다.\n", "\n", "위 데이터에 있는 문제를 해결해 보죠. 예를 들어, 누락된 데이터는 `NaN`이 아니라 0이 되어야 한다고 결정할 수 있습니다. `fillna()` 메서드를 사용해 모든 `NaN` 값을 어떤 값으로 바꿀 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 106, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:28.031419Z", "iopub.status.busy": "2020-10-16T07:31:28.030067Z", "iopub.status.idle": "2020-10-16T07:31:28.036381Z", "shell.execute_reply": "2020-10-16T07:31:28.035045Z" }, "scrolled": true }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
decnovoctsep
alice0.00.00.00.0
bob0.00.09.00.0
charles0.05.011.00.0
colin0.00.00.00.0
darwin0.011.010.00.0
\n", "
" ], "text/plain": [ " dec nov oct sep\n", "alice 0.0 0.0 0.0 0.0\n", "bob 0.0 0.0 9.0 0.0\n", "charles 0.0 5.0 11.0 0.0\n", "colin 0.0 0.0 0.0 0.0\n", "darwin 0.0 11.0 10.0 0.0" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "(grades + bonus_points).fillna(0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "9월의 점수를 0으로 만드는 것은 공정하지 않습니다. 누락된 점수는 그대로 두고, 누락된 보너스 포인트는 0으로 바꿀 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 107, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:28.066978Z", "iopub.status.busy": "2020-10-16T07:31:28.065621Z", "iopub.status.idle": "2020-10-16T07:31:28.072091Z", "shell.execute_reply": "2020-10-16T07:31:28.070746Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
decnovoctsep
aliceNaN9.08.08.0
bobNaN9.09.010.0
charlesNaN5.011.04.0
colinNaNNaNNaNNaN
darwinNaN11.010.09.0
\n", "
" ], "text/plain": [ " dec nov oct sep\n", "alice NaN 9.0 8.0 8.0\n", "bob NaN 9.0 9.0 10.0\n", "charles NaN 5.0 11.0 4.0\n", "colin NaN NaN NaN NaN\n", "darwin NaN 11.0 10.0 9.0" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fixed_bonus_points = bonus_points.fillna(0)\n", "fixed_bonus_points.insert(0, \"sep\", 0)\n", "fixed_bonus_points.loc[\"alice\"] = 0\n", "grades + fixed_bonus_points" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "훨씬 낫네요: 일부 데이터를 꾸며냈지만 덜 불공정합니다.\n", "\n", "누락된 값을 다루는 또 다른 방법은 보간입니다. `bonus_points` `DataFrame`을 다시 보죠:" ] }, { "cell_type": "code", "execution_count": 108, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:28.088876Z", "iopub.status.busy": "2020-10-16T07:31:28.087481Z", "iopub.status.idle": "2020-10-16T07:31:28.093651Z", "shell.execute_reply": "2020-10-16T07:31:28.092464Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
octnovdec
bob0.0NaN2.0
colinNaN1.00.0
darwin0.01.00.0
charles3.03.00.0
\n", "
" ], "text/plain": [ " oct nov dec\n", "bob 0.0 NaN 2.0\n", "colin NaN 1.0 0.0\n", "darwin 0.0 1.0 0.0\n", "charles 3.0 3.0 0.0" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "bonus_points" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`interpolate` 메서드를 사용해 보죠. 기본적으로 수직 방향(`axis=0`)으로 보간합니다. 따라서 수평으로(`axis=1`)으로 보간하도록 지정합니다." ] }, { "cell_type": "code", "execution_count": 109, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:28.114424Z", "iopub.status.busy": "2020-10-16T07:31:28.113078Z", "iopub.status.idle": "2020-10-16T07:31:28.119895Z", "shell.execute_reply": "2020-10-16T07:31:28.118779Z" }, "scrolled": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
octnovdec
bob0.01.02.0
colinNaN1.00.0
darwin0.01.00.0
charles3.03.00.0
\n", "
" ], "text/plain": [ " oct nov dec\n", "bob 0.0 1.0 2.0\n", "colin NaN 1.0 0.0\n", "darwin 0.0 1.0 0.0\n", "charles 3.0 3.0 0.0" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "bonus_points.interpolate(axis=1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "bob의 보너스 포인트는 10월에 0이고 12월에 2입니다. 11월을 보간하면 평균 보너스 포인트 1을 얻습니다. colin의 보너스 포인트는 11월에 1이지만 9월에 포인트는 얼마인지 모릅니다. 따라서 보간할 수 없고 10월의 포인트는 그대로 누락된 값으로 남아 있습니다. 이를 해결하려면 보간하기 전에 9월의 보너스 포인트를 0으로 설정해야 합니다." ] }, { "cell_type": "code", "execution_count": 110, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:28.147938Z", "iopub.status.busy": "2020-10-16T07:31:28.146576Z", "iopub.status.idle": "2020-10-16T07:31:28.152995Z", "shell.execute_reply": "2020-10-16T07:31:28.151814Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
sepoctnovdec
bob0.00.01.02.0
colin0.00.51.00.0
darwin0.00.01.00.0
charles0.03.03.00.0
alice0.00.00.00.0
\n", "
" ], "text/plain": [ " sep oct nov dec\n", "bob 0.0 0.0 1.0 2.0\n", "colin 0.0 0.5 1.0 0.0\n", "darwin 0.0 0.0 1.0 0.0\n", "charles 0.0 3.0 3.0 0.0\n", "alice 0.0 0.0 0.0 0.0" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "better_bonus_points = bonus_points.copy()\n", "better_bonus_points.insert(0, \"sep\", 0)\n", "better_bonus_points.loc[\"alice\"] = 0\n", "better_bonus_points = better_bonus_points.interpolate(axis=1)\n", "better_bonus_points" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "좋습니다. 이제 모든 보너스 포인트가 합리적으로 보간되었습니다. 최종 점수를 확인해 보죠:" ] }, { "cell_type": "code", "execution_count": 111, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:28.175899Z", "iopub.status.busy": "2020-10-16T07:31:28.174553Z", "iopub.status.idle": "2020-10-16T07:31:28.181130Z", "shell.execute_reply": "2020-10-16T07:31:28.179772Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
decnovoctsep
aliceNaN9.08.08.0
bobNaN10.09.010.0
charlesNaN5.011.04.0
colinNaNNaNNaNNaN
darwinNaN11.010.09.0
\n", "
" ], "text/plain": [ " dec nov oct sep\n", "alice NaN 9.0 8.0 8.0\n", "bob NaN 10.0 9.0 10.0\n", "charles NaN 5.0 11.0 4.0\n", "colin NaN NaN NaN NaN\n", "darwin NaN 11.0 10.0 9.0" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "grades + better_bonus_points" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "9월 열이 오른쪽에 추가되었는데 좀 이상합니다. 이는 더하려는 `DataFrame`이 정확히 같은 열을 가지고 있지 않기 때문입니다(`grade` `DataFrame`에는 `\"dec\"` 열이 없습니다). 따라서 판다스는 알파벳 순서로 최종 열을 정렬합니다. 이를 해결하려면 덧셈을 하기 전에 누락된 열을 추가하면 됩니다:" ] }, { "cell_type": "code", "execution_count": 112, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:28.202239Z", "iopub.status.busy": "2020-10-16T07:31:28.200876Z", "iopub.status.idle": "2020-10-16T07:31:28.207279Z", "shell.execute_reply": "2020-10-16T07:31:28.206121Z" }, "scrolled": true }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
sepoctnovdec
alice8.08.09.0NaN
bob10.09.010.0NaN
charles4.011.05.0NaN
colinNaNNaNNaNNaN
darwin9.010.011.0NaN
\n", "
" ], "text/plain": [ " sep oct nov dec\n", "alice 8.0 8.0 9.0 NaN\n", "bob 10.0 9.0 10.0 NaN\n", "charles 4.0 11.0 5.0 NaN\n", "colin NaN NaN NaN NaN\n", "darwin 9.0 10.0 11.0 NaN" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "grades[\"dec\"] = np.nan\n", "final_grades = grades + better_bonus_points\n", "final_grades" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "12월과 colin에 대해 할 수 있는 것이 많지 않습니다. 보너스 포인트를 만드는 것이 나쁘지만 점수를 합리적으로 올릴 수는 없습니다(어떤 선생님들은 그럴 수 있지만). `dropna()` 메서드를 사용해 모두 `NaN`인 행을 삭제합니다:" ] }, { "cell_type": "code", "execution_count": 113, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:28.226459Z", "iopub.status.busy": "2020-10-16T07:31:28.225200Z", "iopub.status.idle": "2020-10-16T07:31:28.231887Z", "shell.execute_reply": "2020-10-16T07:31:28.230844Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
sepoctnovdec
alice8.08.09.0NaN
bob10.09.010.0NaN
charles4.011.05.0NaN
darwin9.010.011.0NaN
\n", "
" ], "text/plain": [ " sep oct nov dec\n", "alice 8.0 8.0 9.0 NaN\n", "bob 10.0 9.0 10.0 NaN\n", "charles 4.0 11.0 5.0 NaN\n", "darwin 9.0 10.0 11.0 NaN" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "final_grades_clean = final_grades.dropna(how=\"all\")\n", "final_grades_clean" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "그다음 `axis` 매개변수를 `1`로 지정하여 모두 `NaN`인 열을 삭제합니다:" ] }, { "cell_type": "code", "execution_count": 114, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:28.249932Z", "iopub.status.busy": "2020-10-16T07:31:28.248633Z", "iopub.status.idle": "2020-10-16T07:31:28.255413Z", "shell.execute_reply": "2020-10-16T07:31:28.254162Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
sepoctnov
alice8.08.09.0
bob10.09.010.0
charles4.011.05.0
darwin9.010.011.0
\n", "
" ], "text/plain": [ " sep oct nov\n", "alice 8.0 8.0 9.0\n", "bob 10.0 9.0 10.0\n", "charles 4.0 11.0 5.0\n", "darwin 9.0 10.0 11.0" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "final_grades_clean = final_grades_clean.dropna(axis=1, how=\"all\")\n", "final_grades_clean" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## `groupby`로 집계하기\n", "\n", "SQL과 비슷하게 판다스는 데이터를 그룹핑하고 각 그룹에 대해 연산을 수행할 수 있습니다.\n", "\n", "먼저 그루핑을 위해 각 사람의 데이터를 추가로 만들겠습니다. `NaN` 값을 어떻게 다루는지 보기 위해 `final_grades` `DataFrame`을 다시 사용하겠습니다:" ] }, { "cell_type": "code", "execution_count": 115, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:28.275015Z", "iopub.status.busy": "2020-10-16T07:31:28.273759Z", "iopub.status.idle": "2020-10-16T07:31:28.280854Z", "shell.execute_reply": "2020-10-16T07:31:28.279781Z" }, "scrolled": true }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
sepoctnovdechobby
alice8.08.09.0NaNBiking
bob10.09.010.0NaNDancing
charles4.011.05.0NaNNaN
colinNaNNaNNaNNaNDancing
darwin9.010.011.0NaNBiking
\n", "
" ], "text/plain": [ " sep oct nov dec hobby\n", "alice 8.0 8.0 9.0 NaN Biking\n", "bob 10.0 9.0 10.0 NaN Dancing\n", "charles 4.0 11.0 5.0 NaN NaN\n", "colin NaN NaN NaN NaN Dancing\n", "darwin 9.0 10.0 11.0 NaN Biking" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "final_grades[\"hobby\"] = [\"Biking\", \"Dancing\", np.nan, \"Dancing\", \"Biking\"]\n", "final_grades" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "hobby로 이 `DataFrame`을 그룹핑해 보죠:" ] }, { "cell_type": "code", "execution_count": 116, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:28.289508Z", "iopub.status.busy": "2020-10-16T07:31:28.288213Z", "iopub.status.idle": "2020-10-16T07:31:28.293911Z", "shell.execute_reply": "2020-10-16T07:31:28.294840Z" } }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "grouped_grades = final_grades.groupby(\"hobby\")\n", "grouped_grades" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "이제 hobby마다 평균 점수를 계산할 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 117, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:28.315872Z", "iopub.status.busy": "2020-10-16T07:31:28.314695Z", "iopub.status.idle": "2020-10-16T07:31:28.320059Z", "shell.execute_reply": "2020-10-16T07:31:28.321150Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
sepoctnovdec
hobby
Biking8.59.010.0NaN
Dancing10.09.010.0NaN
\n", "
" ], "text/plain": [ " sep oct nov dec\n", "hobby \n", "Biking 8.5 9.0 10.0 NaN\n", "Dancing 10.0 9.0 10.0 NaN" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "grouped_grades.mean()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "아주 쉽네요! 평균을 계산할 때 `NaN` 값은 그냥 무시됩니다." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 피봇 테이블\n", "\n", "판다스는 스프레드시트와 비슷하 [피봇 테이블](https://en.wikipedia.org/wiki/Pivot_table)을 지원하여 데이터를 빠르게 요약할 수 있습니다. 어떻게 동작하는 알아 보기 위해 간단한 `DataFrame`을 만들어 보죠:" ] }, { "cell_type": "code", "execution_count": 118, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:28.337894Z", "iopub.status.busy": "2020-10-16T07:31:28.336559Z", "iopub.status.idle": "2020-10-16T07:31:28.342840Z", "shell.execute_reply": "2020-10-16T07:31:28.341758Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
octnovdec
bob0.0NaN2.0
colinNaN1.00.0
darwin0.01.00.0
charles3.03.00.0
\n", "
" ], "text/plain": [ " oct nov dec\n", "bob 0.0 NaN 2.0\n", "colin NaN 1.0 0.0\n", "darwin 0.0 1.0 0.0\n", "charles 3.0 3.0 0.0" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "bonus_points" ] }, { "cell_type": "code", "execution_count": 119, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:28.368578Z", "iopub.status.busy": "2020-10-16T07:31:28.367317Z", "iopub.status.idle": "2020-10-16T07:31:28.374218Z", "shell.execute_reply": "2020-10-16T07:31:28.373063Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
namemonthgradebonus
0alicesep8.0NaN
1aliceoct8.0NaN
2alicenov9.0NaN
3bobsep10.00.0
4boboct9.0NaN
5bobnov10.02.0
6charlessep4.03.0
7charlesoct11.03.0
8charlesnov5.00.0
9darwinsep9.00.0
10darwinoct10.01.0
11darwinnov11.00.0
\n", "
" ], "text/plain": [ " name month grade bonus\n", "0 alice sep 8.0 NaN\n", "1 alice oct 8.0 NaN\n", "2 alice nov 9.0 NaN\n", "3 bob sep 10.0 0.0\n", "4 bob oct 9.0 NaN\n", "5 bob nov 10.0 2.0\n", "6 charles sep 4.0 3.0\n", "7 charles oct 11.0 3.0\n", "8 charles nov 5.0 0.0\n", "9 darwin sep 9.0 0.0\n", "10 darwin oct 10.0 1.0\n", "11 darwin nov 11.0 0.0" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "more_grades = final_grades_clean.stack().reset_index()\n", "more_grades.columns = [\"name\", \"month\", \"grade\"]\n", "more_grades[\"bonus\"] = [np.nan, np.nan, np.nan, 0, np.nan, 2, 3, 3, 0, 0, 1, 0]\n", "more_grades" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "이제 이 `DataFrame`에 대해 `pd.pivot_table()` 함수를 호출하고 `name` 열로 그룹핑합니다. 기본적으로 `pivot_table()`은 수치 열의 평균을 계산합니다:" ] }, { "cell_type": "code", "execution_count": 120, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:28.396388Z", "iopub.status.busy": "2020-10-16T07:31:28.384014Z", "iopub.status.idle": "2020-10-16T07:31:28.402172Z", "shell.execute_reply": "2020-10-16T07:31:28.403481Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
bonusgrade
name
aliceNaN8.333333
bob1.0000009.666667
charles2.0000006.666667
darwin0.33333310.000000
\n", "
" ], "text/plain": [ " bonus grade\n", "name \n", "alice NaN 8.333333\n", "bob 1.000000 9.666667\n", "charles 2.000000 6.666667\n", "darwin 0.333333 10.000000" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.pivot_table(more_grades, index=\"name\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "집계 함수를 `aggfunc` 매개변수로 바꿀 수 있습니다. 또한 집계 대상의 열을 리스트로 지정할 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 121, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:28.429813Z", "iopub.status.busy": "2020-10-16T07:31:28.428152Z", "iopub.status.idle": "2020-10-16T07:31:28.433948Z", "shell.execute_reply": "2020-10-16T07:31:28.435250Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
bonusgrade
name
aliceNaN9.0
bob2.010.0
charles3.011.0
darwin1.011.0
\n", "
" ], "text/plain": [ " bonus grade\n", "name \n", "alice NaN 9.0\n", "bob 2.0 10.0\n", "charles 3.0 11.0\n", "darwin 1.0 11.0" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.pivot_table(more_grades, index=\"name\", values=[\"grade\",\"bonus\"], aggfunc=np.max)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`columns` 매개변수를 지정하여 수평으로 집계할 수 있고 `margins=True`로 설정해 각 행과 열에 대해 전체 합을 계산할 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 122, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:28.447027Z", "iopub.status.busy": "2020-10-16T07:31:28.445382Z", "iopub.status.idle": "2020-10-16T07:31:28.501446Z", "shell.execute_reply": "2020-10-16T07:31:28.500477Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
monthnovoctsepAll
name
alice9.008.08.008.333333
bob10.009.010.009.666667
charles5.0011.04.006.666667
darwin11.0010.09.0010.000000
All8.759.57.758.666667
\n", "
" ], "text/plain": [ "month nov oct sep All\n", "name \n", "alice 9.00 8.0 8.00 8.333333\n", "bob 10.00 9.0 10.00 9.666667\n", "charles 5.00 11.0 4.00 6.666667\n", "darwin 11.00 10.0 9.00 10.000000\n", "All 8.75 9.5 7.75 8.666667" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.pivot_table(more_grades, index=\"name\", values=\"grade\", columns=\"month\", margins=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "마지막으로 여러 개의 인덱스나 열 이름을 지정하면 판다스가 다중 레벨 인덱스를 만듭니다:" ] }, { "cell_type": "code", "execution_count": 123, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:28.538598Z", "iopub.status.busy": "2020-10-16T07:31:28.516477Z", "iopub.status.idle": "2020-10-16T07:31:28.544991Z", "shell.execute_reply": "2020-10-16T07:31:28.543793Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
bonusgrade
namemonth
alicenovNaN9.00
octNaN8.00
sepNaN8.00
bobnov2.00010.00
octNaN9.00
sep0.00010.00
charlesnov0.0005.00
oct3.00011.00
sep3.0004.00
darwinnov0.00011.00
oct1.00010.00
sep0.0009.00
All1.1258.75
\n", "
" ], "text/plain": [ " bonus grade\n", "name month \n", "alice nov NaN 9.00\n", " oct NaN 8.00\n", " sep NaN 8.00\n", "bob nov 2.000 10.00\n", " oct NaN 9.00\n", " sep 0.000 10.00\n", "charles nov 0.000 5.00\n", " oct 3.000 11.00\n", " sep 3.000 4.00\n", "darwin nov 0.000 11.00\n", " oct 1.000 10.00\n", " sep 0.000 9.00\n", "All 1.125 8.75" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.pivot_table(more_grades, index=(\"name\", \"month\"), margins=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 함수\n", "\n", "큰 `DataFrame`을 다룰 때 내용을 간단히 요약하는 것이 도움이 됩니다. 판다스는 이를 위한 몇 가지 함수를 제공합니다. 먼저 수치 값, 누락된 값, 텍스트 값이 섞인 큰 `DataFrame`을 만들어 보죠. 주피터 노트북은 이 `DataFrame`의 일부만 보여줍니다:" ] }, { "cell_type": "code", "execution_count": 124, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:28.555609Z", "iopub.status.busy": "2020-10-16T07:31:28.554261Z", "iopub.status.idle": "2020-10-16T07:31:28.679610Z", "shell.execute_reply": "2020-10-16T07:31:28.678101Z" }, "scrolled": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
ABCsome_textDEFGHI...QRSTUVWXYZ
0NaN11.044.0Blabla99.0NaN88.022.0165.0143.0...11.0NaN11.044.099.0NaN88.022.0165.0143.0
111.022.055.0Blabla110.0NaN99.033.0NaN154.0...22.011.022.055.0110.0NaN99.033.0NaN154.0
222.033.066.0Blabla121.011.0110.044.0NaN165.0...33.022.033.066.0121.011.0110.044.0NaN165.0
333.044.077.0Blabla132.022.0121.055.011.0NaN...44.033.044.077.0132.022.0121.055.011.0NaN
444.055.088.0Blabla143.033.0132.066.022.0NaN...55.044.055.088.0143.033.0132.066.022.0NaN
..................................................................
9995NaNNaN33.0Blabla88.0165.077.011.0154.0132.0...NaNNaNNaN33.088.0165.077.011.0154.0132.0
9996NaN11.044.0Blabla99.0NaN88.022.0165.0143.0...11.0NaN11.044.099.0NaN88.022.0165.0143.0
999711.022.055.0Blabla110.0NaN99.033.0NaN154.0...22.011.022.055.0110.0NaN99.033.0NaN154.0
999822.033.066.0Blabla121.011.0110.044.0NaN165.0...33.022.033.066.0121.011.0110.044.0NaN165.0
999933.044.077.0Blabla132.022.0121.055.011.0NaN...44.033.044.077.0132.022.0121.055.011.0NaN
\n", "

10000 rows × 27 columns

\n", "
" ], "text/plain": [ " A B C some_text D E F G H I \\\n", "0 NaN 11.0 44.0 Blabla 99.0 NaN 88.0 22.0 165.0 143.0 \n", "1 11.0 22.0 55.0 Blabla 110.0 NaN 99.0 33.0 NaN 154.0 \n", "2 22.0 33.0 66.0 Blabla 121.0 11.0 110.0 44.0 NaN 165.0 \n", "3 33.0 44.0 77.0 Blabla 132.0 22.0 121.0 55.0 11.0 NaN \n", "4 44.0 55.0 88.0 Blabla 143.0 33.0 132.0 66.0 22.0 NaN \n", "... ... ... ... ... ... ... ... ... ... ... \n", "9995 NaN NaN 33.0 Blabla 88.0 165.0 77.0 11.0 154.0 132.0 \n", "9996 NaN 11.0 44.0 Blabla 99.0 NaN 88.0 22.0 165.0 143.0 \n", "9997 11.0 22.0 55.0 Blabla 110.0 NaN 99.0 33.0 NaN 154.0 \n", "9998 22.0 33.0 66.0 Blabla 121.0 11.0 110.0 44.0 NaN 165.0 \n", "9999 33.0 44.0 77.0 Blabla 132.0 22.0 121.0 55.0 11.0 NaN \n", "\n", " ... Q R S T U V W X Y Z \n", "0 ... 11.0 NaN 11.0 44.0 99.0 NaN 88.0 22.0 165.0 143.0 \n", "1 ... 22.0 11.0 22.0 55.0 110.0 NaN 99.0 33.0 NaN 154.0 \n", "2 ... 33.0 22.0 33.0 66.0 121.0 11.0 110.0 44.0 NaN 165.0 \n", "3 ... 44.0 33.0 44.0 77.0 132.0 22.0 121.0 55.0 11.0 NaN \n", "4 ... 55.0 44.0 55.0 88.0 143.0 33.0 132.0 66.0 22.0 NaN \n", "... ... ... ... ... ... ... ... ... ... ... ... \n", "9995 ... NaN NaN NaN 33.0 88.0 165.0 77.0 11.0 154.0 132.0 \n", "9996 ... 11.0 NaN 11.0 44.0 99.0 NaN 88.0 22.0 165.0 143.0 \n", "9997 ... 22.0 11.0 22.0 55.0 110.0 NaN 99.0 33.0 NaN 154.0 \n", "9998 ... 33.0 22.0 33.0 66.0 121.0 11.0 110.0 44.0 NaN 165.0 \n", "9999 ... 44.0 33.0 44.0 77.0 132.0 22.0 121.0 55.0 11.0 NaN \n", "\n", "[10000 rows x 27 columns]" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "much_data = np.fromfunction(lambda x,y: (x+y*y)%17*11, (10000, 26))\n", "large_df = pd.DataFrame(much_data, columns=list(\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"))\n", "large_df[large_df % 16 == 0] = np.nan\n", "large_df.insert(3,\"some_text\", \"Blabla\")\n", "large_df" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`head()` 메서드는 처음 5개 행을 반환합니다:" ] }, { "cell_type": "code", "execution_count": 125, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:28.722714Z", "iopub.status.busy": "2020-10-16T07:31:28.715602Z", "iopub.status.idle": "2020-10-16T07:31:28.729780Z", "shell.execute_reply": "2020-10-16T07:31:28.728244Z" }, "scrolled": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
ABCsome_textDEFGHI...QRSTUVWXYZ
0NaN11.044.0Blabla99.0NaN88.022.0165.0143.0...11.0NaN11.044.099.0NaN88.022.0165.0143.0
111.022.055.0Blabla110.0NaN99.033.0NaN154.0...22.011.022.055.0110.0NaN99.033.0NaN154.0
222.033.066.0Blabla121.011.0110.044.0NaN165.0...33.022.033.066.0121.011.0110.044.0NaN165.0
333.044.077.0Blabla132.022.0121.055.011.0NaN...44.033.044.077.0132.022.0121.055.011.0NaN
444.055.088.0Blabla143.033.0132.066.022.0NaN...55.044.055.088.0143.033.0132.066.022.0NaN
\n", "

5 rows × 27 columns

\n", "
" ], "text/plain": [ " A B C some_text D E F G H I ... \\\n", "0 NaN 11.0 44.0 Blabla 99.0 NaN 88.0 22.0 165.0 143.0 ... \n", "1 11.0 22.0 55.0 Blabla 110.0 NaN 99.0 33.0 NaN 154.0 ... \n", "2 22.0 33.0 66.0 Blabla 121.0 11.0 110.0 44.0 NaN 165.0 ... \n", "3 33.0 44.0 77.0 Blabla 132.0 22.0 121.0 55.0 11.0 NaN ... \n", "4 44.0 55.0 88.0 Blabla 143.0 33.0 132.0 66.0 22.0 NaN ... \n", "\n", " Q R S T U V W X Y Z \n", "0 11.0 NaN 11.0 44.0 99.0 NaN 88.0 22.0 165.0 143.0 \n", "1 22.0 11.0 22.0 55.0 110.0 NaN 99.0 33.0 NaN 154.0 \n", "2 33.0 22.0 33.0 66.0 121.0 11.0 110.0 44.0 NaN 165.0 \n", "3 44.0 33.0 44.0 77.0 132.0 22.0 121.0 55.0 11.0 NaN \n", "4 55.0 44.0 55.0 88.0 143.0 33.0 132.0 66.0 22.0 NaN \n", "\n", "[5 rows x 27 columns]" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "large_df.head()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "마지막 5개 행을 반환하는 `tail()` 함수도 있습니다. 원하는 행 개수를 전달할 수도 있습니다:" ] }, { "cell_type": "code", "execution_count": 126, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:28.770715Z", "iopub.status.busy": "2020-10-16T07:31:28.768959Z", "iopub.status.idle": "2020-10-16T07:31:28.775307Z", "shell.execute_reply": "2020-10-16T07:31:28.776741Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
ABCsome_textDEFGHI...QRSTUVWXYZ
999822.033.066.0Blabla121.011.0110.044.0NaN165.0...33.022.033.066.0121.011.0110.044.0NaN165.0
999933.044.077.0Blabla132.022.0121.055.011.0NaN...44.033.044.077.0132.022.0121.055.011.0NaN
\n", "

2 rows × 27 columns

\n", "
" ], "text/plain": [ " A B C some_text D E F G H I ... \\\n", "9998 22.0 33.0 66.0 Blabla 121.0 11.0 110.0 44.0 NaN 165.0 ... \n", "9999 33.0 44.0 77.0 Blabla 132.0 22.0 121.0 55.0 11.0 NaN ... \n", "\n", " Q R S T U V W X Y Z \n", "9998 33.0 22.0 33.0 66.0 121.0 11.0 110.0 44.0 NaN 165.0 \n", "9999 44.0 33.0 44.0 77.0 132.0 22.0 121.0 55.0 11.0 NaN \n", "\n", "[2 rows x 27 columns]" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "large_df.tail(n=2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`info()` 메서드는 각 열의 내용을 요약하여 출력합니다:" ] }, { "cell_type": "code", "execution_count": 127, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:28.790461Z", "iopub.status.busy": "2020-10-16T07:31:28.789327Z", "iopub.status.idle": "2020-10-16T07:31:28.806423Z", "shell.execute_reply": "2020-10-16T07:31:28.805155Z" }, "scrolled": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "RangeIndex: 10000 entries, 0 to 9999\n", "Data columns (total 27 columns):\n", " # Column Non-Null Count Dtype \n", "--- ------ -------------- ----- \n", " 0 A 8823 non-null float64\n", " 1 B 8824 non-null float64\n", " 2 C 8824 non-null float64\n", " 3 some_text 10000 non-null object \n", " 4 D 8824 non-null float64\n", " 5 E 8822 non-null float64\n", " 6 F 8824 non-null float64\n", " 7 G 8824 non-null float64\n", " 8 H 8822 non-null float64\n", " 9 I 8823 non-null float64\n", " 10 J 8823 non-null float64\n", " 11 K 8822 non-null float64\n", " 12 L 8824 non-null float64\n", " 13 M 8824 non-null float64\n", " 14 N 8822 non-null float64\n", " 15 O 8824 non-null float64\n", " 16 P 8824 non-null float64\n", " 17 Q 8824 non-null float64\n", " 18 R 8823 non-null float64\n", " 19 S 8824 non-null float64\n", " 20 T 8824 non-null float64\n", " 21 U 8824 non-null float64\n", " 22 V 8822 non-null float64\n", " 23 W 8824 non-null float64\n", " 24 X 8824 non-null float64\n", " 25 Y 8822 non-null float64\n", " 26 Z 8823 non-null float64\n", "dtypes: float64(26), object(1)\n", "memory usage: 2.1+ MB\n" ] } ], "source": [ "large_df.info()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "마지막으로 `describe()` 메서드는 각 열에 대한 주요 집계 연산을 수행한 결과를 보여줍니다:\n", "\n", "Finally, the `describe()` method gives a nice overview of the main aggregated values over each column:\n", "* `count`: null(NaN)이 아닌 값의 개수\n", "* `mean`: null이 아닌 값의 평균\n", "* `std`: null이 아닌 값의 [표준 편차](https://ko.wikipedia.org/wiki/%ED%91%9C%EC%A4%80_%ED%8E%B8%EC%B0%A8)\n", "* `min`: null이 아닌 값의 최솟값\n", "* `25%`, `50%`, `75%`: null이 아닌 값의 25번째, 50번째, 75번째 [백분위수](https://ko.wikipedia.org/wiki/%EB%B0%B1%EB%B6%84%EC%9C%84%EC%88%98)\n", "* `max`: null이 아닌 값의 최댓값" ] }, { "cell_type": "code", "execution_count": 128, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:28.816862Z", "iopub.status.busy": "2020-10-16T07:31:28.815373Z", "iopub.status.idle": "2020-10-16T07:31:28.980652Z", "shell.execute_reply": "2020-10-16T07:31:28.979733Z" }, "scrolled": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
ABCDEFGHIJ...QRSTUVWXYZ
count8823.0000008824.0000008824.0000008824.0000008822.0000008824.0000008824.0000008822.0000008823.0000008823.000000...8824.0000008823.0000008824.0000008824.0000008824.0000008822.0000008824.0000008824.0000008822.0000008823.000000
mean87.97755987.97257587.98753488.01246687.98379188.00748087.97756188.00000088.02244188.022441...87.97257587.97755987.97257587.98753488.01246687.98379188.00748087.97756188.00000088.022441
std47.53591147.53552347.52167947.52167947.53500147.51937147.52975547.53687947.53591147.535911...47.53552347.53591147.53552347.52167947.52167947.53500147.51937147.52975547.53687947.535911
min11.00000011.00000011.00000011.00000011.00000011.00000011.00000011.00000011.00000011.000000...11.00000011.00000011.00000011.00000011.00000011.00000011.00000011.00000011.00000011.000000
25%44.00000044.00000044.00000044.00000044.00000044.00000044.00000044.00000044.00000044.000000...44.00000044.00000044.00000044.00000044.00000044.00000044.00000044.00000044.00000044.000000
50%88.00000088.00000088.00000088.00000088.00000088.00000088.00000088.00000088.00000088.000000...88.00000088.00000088.00000088.00000088.00000088.00000088.00000088.00000088.00000088.000000
75%132.000000132.000000132.000000132.000000132.000000132.000000132.000000132.000000132.000000132.000000...132.000000132.000000132.000000132.000000132.000000132.000000132.000000132.000000132.000000132.000000
max165.000000165.000000165.000000165.000000165.000000165.000000165.000000165.000000165.000000165.000000...165.000000165.000000165.000000165.000000165.000000165.000000165.000000165.000000165.000000165.000000
\n", "

8 rows × 26 columns

\n", "
" ], "text/plain": [ " A B C D E \\\n", "count 8823.000000 8824.000000 8824.000000 8824.000000 8822.000000 \n", "mean 87.977559 87.972575 87.987534 88.012466 87.983791 \n", "std 47.535911 47.535523 47.521679 47.521679 47.535001 \n", "min 11.000000 11.000000 11.000000 11.000000 11.000000 \n", "25% 44.000000 44.000000 44.000000 44.000000 44.000000 \n", "50% 88.000000 88.000000 88.000000 88.000000 88.000000 \n", "75% 132.000000 132.000000 132.000000 132.000000 132.000000 \n", "max 165.000000 165.000000 165.000000 165.000000 165.000000 \n", "\n", " F G H I J ... \\\n", "count 8824.000000 8824.000000 8822.000000 8823.000000 8823.000000 ... \n", "mean 88.007480 87.977561 88.000000 88.022441 88.022441 ... \n", "std 47.519371 47.529755 47.536879 47.535911 47.535911 ... \n", "min 11.000000 11.000000 11.000000 11.000000 11.000000 ... \n", "25% 44.000000 44.000000 44.000000 44.000000 44.000000 ... \n", "50% 88.000000 88.000000 88.000000 88.000000 88.000000 ... \n", "75% 132.000000 132.000000 132.000000 132.000000 132.000000 ... \n", "max 165.000000 165.000000 165.000000 165.000000 165.000000 ... \n", "\n", " Q R S T U \\\n", "count 8824.000000 8823.000000 8824.000000 8824.000000 8824.000000 \n", "mean 87.972575 87.977559 87.972575 87.987534 88.012466 \n", "std 47.535523 47.535911 47.535523 47.521679 47.521679 \n", "min 11.000000 11.000000 11.000000 11.000000 11.000000 \n", "25% 44.000000 44.000000 44.000000 44.000000 44.000000 \n", "50% 88.000000 88.000000 88.000000 88.000000 88.000000 \n", "75% 132.000000 132.000000 132.000000 132.000000 132.000000 \n", "max 165.000000 165.000000 165.000000 165.000000 165.000000 \n", "\n", " V W X Y Z \n", "count 8822.000000 8824.000000 8824.000000 8822.000000 8823.000000 \n", "mean 87.983791 88.007480 87.977561 88.000000 88.022441 \n", "std 47.535001 47.519371 47.529755 47.536879 47.535911 \n", "min 11.000000 11.000000 11.000000 11.000000 11.000000 \n", "25% 44.000000 44.000000 44.000000 44.000000 44.000000 \n", "50% 88.000000 88.000000 88.000000 88.000000 88.000000 \n", "75% 132.000000 132.000000 132.000000 132.000000 132.000000 \n", "max 165.000000 165.000000 165.000000 165.000000 165.000000 \n", "\n", "[8 rows x 26 columns]" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "large_df.describe()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 저장 & 로딩\n", "\n", "판다스는 `DataFrame`를 여러 가지 포맷으로 저장할 수 있습니다. CSV, Excel, JSON, HTML, HDF5, SQL 데이터베이스 같은 포맷이 가능합니다. 예제를 위해 `DataFrame`을 하나 만들어 보겠습니다:" ] }, { "cell_type": "code", "execution_count": 129, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:29.000434Z", "iopub.status.busy": "2020-10-16T07:31:28.999329Z", "iopub.status.idle": "2020-10-16T07:31:29.004808Z", "shell.execute_reply": "2020-10-16T07:31:29.005902Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
hobbyweightbirthyearchildren
aliceBiking68.51985NaN
bobDancing83.119843.0
\n", "
" ], "text/plain": [ " hobby weight birthyear children\n", "alice Biking 68.5 1985 NaN\n", "bob Dancing 83.1 1984 3.0" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "my_df = pd.DataFrame(\n", " [[\"Biking\", 68.5, 1985, np.nan], [\"Dancing\", 83.1, 1984, 3]], \n", " columns=[\"hobby\",\"weight\",\"birthyear\",\"children\"],\n", " index=[\"alice\", \"bob\"]\n", ")\n", "my_df" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 저장\n", "\n", "CSV, HTML, JSON로 저장해 보죠:" ] }, { "cell_type": "code", "execution_count": 130, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:29.014207Z", "iopub.status.busy": "2020-10-16T07:31:29.013037Z", "iopub.status.idle": "2020-10-16T07:31:29.057312Z", "shell.execute_reply": "2020-10-16T07:31:29.056173Z" } }, "outputs": [], "source": [ "my_df.to_csv(\"my_df.csv\")\n", "my_df.to_html(\"my_df.html\")\n", "my_df.to_json(\"my_df.json\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "저장된 내용을 확인해 보죠:" ] }, { "cell_type": "code", "execution_count": 131, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:29.067993Z", "iopub.status.busy": "2020-10-16T07:31:29.066881Z", "iopub.status.idle": "2020-10-16T07:31:29.081991Z", "shell.execute_reply": "2020-10-16T07:31:29.080808Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "# my_df.csv\n", ",hobby,weight,birthyear,children\n", "alice,Biking,68.5,1985,\n", "bob,Dancing,83.1,1984,3.0\n", "\n", "\n", "# my_df.html\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
hobbyweightbirthyearchildren
aliceBiking68.51985NaN
bobDancing83.119843.0
\n", "\n", "# my_df.json\n", "{\"hobby\":{\"alice\":\"Biking\",\"bob\":\"Dancing\"},\"weight\":{\"alice\":68.5,\"bob\":83.1},\"birthyear\":{\"alice\":1985,\"bob\":1984},\"children\":{\"alice\":null,\"bob\":3.0}}\n", "\n" ] } ], "source": [ "for filename in (\"my_df.csv\", \"my_df.html\", \"my_df.json\"):\n", " print(\"#\", filename)\n", " with open(filename, \"rt\") as f:\n", " print(f.read())\n", " print()\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "인덱스는 (이름 없이) CSV 파일의 첫 번째 열에 저장되었습니다. HTML에서는 `` 태그와 JSON에서는 키로 저장되었습니다.\n", "\n", "다른 포맷으로 저장하는 것도 비슷합니다. 하지만 일부 포맷은 추가적인 라이브러리 설치가 필요합니다. 예를 들어, 엑셀로 저장하려면 openpyxl 라이브러리가 필요합니다:" ] }, { "cell_type": "code", "execution_count": 132, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:29.092332Z", "iopub.status.busy": "2020-10-16T07:31:29.090986Z", "iopub.status.idle": "2020-10-16T07:31:29.098706Z", "shell.execute_reply": "2020-10-16T07:31:29.097724Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "No module named 'openpyxl'\n" ] } ], "source": [ "try:\n", " my_df.to_excel(\"my_df.xlsx\", sheet_name='People')\n", "except ImportError as e:\n", " print(e)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 로딩\n", "\n", "CSV 파일을 `DataFrame`으로 로드해 보죠:" ] }, { "cell_type": "code", "execution_count": 133, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:29.107752Z", "iopub.status.busy": "2020-10-16T07:31:29.106586Z", "iopub.status.idle": "2020-10-16T07:31:29.126178Z", "shell.execute_reply": "2020-10-16T07:31:29.124769Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
hobbyweightbirthyearchildren
aliceBiking68.51985NaN
bobDancing83.119843.0
\n", "
" ], "text/plain": [ " hobby weight birthyear children\n", "alice Biking 68.5 1985 NaN\n", "bob Dancing 83.1 1984 3.0" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "my_df_loaded = pd.read_csv(\"my_df.csv\", index_col=0)\n", "my_df_loaded" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "예상할 수 있듯이 `read_json`, `read_html`, `read_excel` 함수도 있습니다. 인터넷에서 데이터를 바로 읽을 수도 있습니다. 예를 들어 깃허브에서 1,000개의 U.S. 도시를 로드해 보죠:" ] }, { "cell_type": "code", "execution_count": 134, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:29.140192Z", "iopub.status.busy": "2020-10-16T07:31:29.138604Z", "iopub.status.idle": "2020-10-16T07:31:29.323556Z", "shell.execute_reply": "2020-10-16T07:31:29.322579Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "HTTP Error 403: Forbidden\n" ] } ], "source": [ "us_cities = None\n", "try:\n", " csv_url = \"https://raw.githubusercontent.com/plotly/datasets/master/us-cities-top-1k.csv\"\n", " us_cities = pd.read_csv(csv_url, index_col=0)\n", " us_cities = us_cities.head()\n", "except IOError as e:\n", " print(e)\n", "us_cities" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "이외에도 많은 옵션이 있습니다. 특히 datetime 포맷에 관련된 옵션이 많습니다. 더 자세한 내용은 온라인 [문서](http://pandas.pydata.org/pandas-docs/stable/io.html)를 참고하세요." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# `DataFrame` 합치기\n", "\n", "## SQL 조인\n", "\n", "판다스의 강력한 기능 중 하나는 `DataFrame`에 대해 SQL 같은 조인(join)을 수행할 수 있는 것입니다. 여러 종류의 조인이 지원됩니다. 이너 조인(inner join), 레프트/라이트 아우터 조인(left/right outer join), 풀 조인(full join)입니다. 이에 대해 알아 보기 위해 간단한 `DataFrame`을 만들어 보죠:" ] }, { "cell_type": "code", "execution_count": 135, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:29.346066Z", "iopub.status.busy": "2020-10-16T07:31:29.344663Z", "iopub.status.idle": "2020-10-16T07:31:29.351634Z", "shell.execute_reply": "2020-10-16T07:31:29.350373Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
statecitylatlng
0CASan Francisco37.781334-122.416728
1NYNew York40.705649-74.008344
2FLMiami25.791100-80.320733
3OHCleveland41.473508-81.739791
4UTSalt Lake City40.755851-111.896657
\n", "
" ], "text/plain": [ " state city lat lng\n", "0 CA San Francisco 37.781334 -122.416728\n", "1 NY New York 40.705649 -74.008344\n", "2 FL Miami 25.791100 -80.320733\n", "3 OH Cleveland 41.473508 -81.739791\n", "4 UT Salt Lake City 40.755851 -111.896657" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "city_loc = pd.DataFrame(\n", " [\n", " [\"CA\", \"San Francisco\", 37.781334, -122.416728],\n", " [\"NY\", \"New York\", 40.705649, -74.008344],\n", " [\"FL\", \"Miami\", 25.791100, -80.320733],\n", " [\"OH\", \"Cleveland\", 41.473508, -81.739791],\n", " [\"UT\", \"Salt Lake City\", 40.755851, -111.896657]\n", " ], columns=[\"state\", \"city\", \"lat\", \"lng\"])\n", "city_loc" ] }, { "cell_type": "code", "execution_count": 136, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:29.372130Z", "iopub.status.busy": "2020-10-16T07:31:29.370659Z", "iopub.status.idle": "2020-10-16T07:31:29.376662Z", "shell.execute_reply": "2020-10-16T07:31:29.375633Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
populationcitystate
3808976San FranciscoCalifornia
48363710New YorkNew-York
5413201MiamiFlorida
62242193HoustonTexas
\n", "
" ], "text/plain": [ " population city state\n", "3 808976 San Francisco California\n", "4 8363710 New York New-York\n", "5 413201 Miami Florida\n", "6 2242193 Houston Texas" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "city_pop = pd.DataFrame(\n", " [\n", " [808976, \"San Francisco\", \"California\"],\n", " [8363710, \"New York\", \"New-York\"],\n", " [413201, \"Miami\", \"Florida\"],\n", " [2242193, \"Houston\", \"Texas\"]\n", " ], index=[3,4,5,6], columns=[\"population\", \"city\", \"state\"])\n", "city_pop" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "이제 `merge()` 함수를 사용해 이 `DataFrame`을 조인해 보죠:" ] }, { "cell_type": "code", "execution_count": 137, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:29.401493Z", "iopub.status.busy": "2020-10-16T07:31:29.400088Z", "iopub.status.idle": "2020-10-16T07:31:29.407147Z", "shell.execute_reply": "2020-10-16T07:31:29.405772Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
state_xcitylatlngpopulationstate_y
0CASan Francisco37.781334-122.416728808976California
1NYNew York40.705649-74.0083448363710New-York
2FLMiami25.791100-80.320733413201Florida
\n", "
" ], "text/plain": [ " state_x city lat lng population state_y\n", "0 CA San Francisco 37.781334 -122.416728 808976 California\n", "1 NY New York 40.705649 -74.008344 8363710 New-York\n", "2 FL Miami 25.791100 -80.320733 413201 Florida" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.merge(left=city_loc, right=city_pop, on=\"city\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "두 `DataFrame`은 `state`란 이름의 열을 가지고 있으므로 `state_x`와 `state_y`로 이름이 바뀌었습니다.\n", "\n", "또한 Cleveland, Salt Lake City, Houston은 두 `DataFrame`에 모두 존재하지 않기 때문에 삭제되었습니다. SQL의 `INNER JOIN`과 동일합니다. 도시를 삭제하지 않고 `NaN`으로 채우는 `FULL OUTER JOIN`을 원하면 `how=\"outer\"`로 지정합니다:" ] }, { "cell_type": "code", "execution_count": 138, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:29.435099Z", "iopub.status.busy": "2020-10-16T07:31:29.433483Z", "iopub.status.idle": "2020-10-16T07:31:29.439267Z", "shell.execute_reply": "2020-10-16T07:31:29.440577Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
state_xcitylatlngpopulationstate_y
0CASan Francisco37.781334-122.416728808976.0California
1NYNew York40.705649-74.0083448363710.0New-York
2FLMiami25.791100-80.320733413201.0Florida
3OHCleveland41.473508-81.739791NaNNaN
4UTSalt Lake City40.755851-111.896657NaNNaN
5NaNHoustonNaNNaN2242193.0Texas
\n", "
" ], "text/plain": [ " state_x city lat lng population state_y\n", "0 CA San Francisco 37.781334 -122.416728 808976.0 California\n", "1 NY New York 40.705649 -74.008344 8363710.0 New-York\n", "2 FL Miami 25.791100 -80.320733 413201.0 Florida\n", "3 OH Cleveland 41.473508 -81.739791 NaN NaN\n", "4 UT Salt Lake City 40.755851 -111.896657 NaN NaN\n", "5 NaN Houston NaN NaN 2242193.0 Texas" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "all_cities = pd.merge(left=city_loc, right=city_pop, on=\"city\", how=\"outer\")\n", "all_cities" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "물론 `LEFT OUTER JOIN`은 `how=\"left\"`로 지정할 수 있습니다. 왼쪽의 `DataFrame`에 있는 도시만 남습니다. 비슷하게 `how=\"right\"`는 오른쪽 `DataFrame`에 있는 도시만 결과에 남습니다. 예를 들면:" ] }, { "cell_type": "code", "execution_count": 139, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:29.465273Z", "iopub.status.busy": "2020-10-16T07:31:29.454940Z", "iopub.status.idle": "2020-10-16T07:31:29.472015Z", "shell.execute_reply": "2020-10-16T07:31:29.470685Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
state_xcitylatlngpopulationstate_y
0CASan Francisco37.781334-122.416728808976California
1NYNew York40.705649-74.0083448363710New-York
2FLMiami25.791100-80.320733413201Florida
3NaNHoustonNaNNaN2242193Texas
\n", "
" ], "text/plain": [ " state_x city lat lng population state_y\n", "0 CA San Francisco 37.781334 -122.416728 808976 California\n", "1 NY New York 40.705649 -74.008344 8363710 New-York\n", "2 FL Miami 25.791100 -80.320733 413201 Florida\n", "3 NaN Houston NaN NaN 2242193 Texas" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.merge(left=city_loc, right=city_pop, on=\"city\", how=\"right\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "조인할 키가 `DataFrame` 인덱스라면 `left_index=True`나 `right_index=True`로 지정해야 합니다. 키 열의 이름이 다르면 `left_on`과 `right_on`을 사용합니다. 예를 들어:" ] }, { "cell_type": "code", "execution_count": 140, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:29.498246Z", "iopub.status.busy": "2020-10-16T07:31:29.496603Z", "iopub.status.idle": "2020-10-16T07:31:29.503085Z", "shell.execute_reply": "2020-10-16T07:31:29.504399Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
state_xcitylatlngpopulationnamestate_y
0CASan Francisco37.781334-122.416728808976San FranciscoCalifornia
1NYNew York40.705649-74.0083448363710New YorkNew-York
2FLMiami25.791100-80.320733413201MiamiFlorida
\n", "
" ], "text/plain": [ " state_x city lat lng population name \\\n", "0 CA San Francisco 37.781334 -122.416728 808976 San Francisco \n", "1 NY New York 40.705649 -74.008344 8363710 New York \n", "2 FL Miami 25.791100 -80.320733 413201 Miami \n", "\n", " state_y \n", "0 California \n", "1 New-York \n", "2 Florida " ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "city_pop2 = city_pop.copy()\n", "city_pop2.columns = [\"population\", \"name\", \"state\"]\n", "pd.merge(left=city_loc, right=city_pop2, left_on=\"city\", right_on=\"name\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 연결\n", "\n", "`DataFrame`을 조인하는 대신 그냥 연결할 수도 있습니다. `concat()` 함수가 하는 일입니다:" ] }, { "cell_type": "code", "execution_count": 141, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:29.528602Z", "iopub.status.busy": "2020-10-16T07:31:29.527026Z", "iopub.status.idle": "2020-10-16T07:31:29.533411Z", "shell.execute_reply": "2020-10-16T07:31:29.532303Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
statecitylatlngpopulation
0CASan Francisco37.781334-122.416728NaN
1NYNew York40.705649-74.008344NaN
2FLMiami25.791100-80.320733NaN
3OHCleveland41.473508-81.739791NaN
4UTSalt Lake City40.755851-111.896657NaN
3CaliforniaSan FranciscoNaNNaN808976.0
4New-YorkNew YorkNaNNaN8363710.0
5FloridaMiamiNaNNaN413201.0
6TexasHoustonNaNNaN2242193.0
\n", "
" ], "text/plain": [ " state city lat lng population\n", "0 CA San Francisco 37.781334 -122.416728 NaN\n", "1 NY New York 40.705649 -74.008344 NaN\n", "2 FL Miami 25.791100 -80.320733 NaN\n", "3 OH Cleveland 41.473508 -81.739791 NaN\n", "4 UT Salt Lake City 40.755851 -111.896657 NaN\n", "3 California San Francisco NaN NaN 808976.0\n", "4 New-York New York NaN NaN 8363710.0\n", "5 Florida Miami NaN NaN 413201.0\n", "6 Texas Houston NaN NaN 2242193.0" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "result_concat = pd.concat([city_loc, city_pop])\n", "result_concat" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "이 연산은 (행을 따라) 수직적으로 데이터를 연결하고 (열을 따라) 수평으로 연결하지 않습니다. 이 예에서 동일한 인덱스를 가진 행이 있습니다(예를 들면 3). 판다스는 이를 우아하게 처리합니다:" ] }, { "cell_type": "code", "execution_count": 142, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:29.552161Z", "iopub.status.busy": "2020-10-16T07:31:29.550911Z", "iopub.status.idle": "2020-10-16T07:31:29.557417Z", "shell.execute_reply": "2020-10-16T07:31:29.556343Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
statecitylatlngpopulation
3OHCleveland41.473508-81.739791NaN
3CaliforniaSan FranciscoNaNNaN808976.0
\n", "
" ], "text/plain": [ " state city lat lng population\n", "3 OH Cleveland 41.473508 -81.739791 NaN\n", "3 California San Francisco NaN NaN 808976.0" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "result_concat.loc[3]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "또는 인덱스를 무시하도록 설정할 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 143, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:29.579980Z", "iopub.status.busy": "2020-10-16T07:31:29.578727Z", "iopub.status.idle": "2020-10-16T07:31:29.585613Z", "shell.execute_reply": "2020-10-16T07:31:29.584416Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
statecitylatlngpopulation
0CASan Francisco37.781334-122.416728NaN
1NYNew York40.705649-74.008344NaN
2FLMiami25.791100-80.320733NaN
3OHCleveland41.473508-81.739791NaN
4UTSalt Lake City40.755851-111.896657NaN
5CaliforniaSan FranciscoNaNNaN808976.0
6New-YorkNew YorkNaNNaN8363710.0
7FloridaMiamiNaNNaN413201.0
8TexasHoustonNaNNaN2242193.0
\n", "
" ], "text/plain": [ " state city lat lng population\n", "0 CA San Francisco 37.781334 -122.416728 NaN\n", "1 NY New York 40.705649 -74.008344 NaN\n", "2 FL Miami 25.791100 -80.320733 NaN\n", "3 OH Cleveland 41.473508 -81.739791 NaN\n", "4 UT Salt Lake City 40.755851 -111.896657 NaN\n", "5 California San Francisco NaN NaN 808976.0\n", "6 New-York New York NaN NaN 8363710.0\n", "7 Florida Miami NaN NaN 413201.0\n", "8 Texas Houston NaN NaN 2242193.0" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.concat([city_loc, city_pop], ignore_index=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "한 `DataFrame`에 열이 없을 때 `NaN`이 채워져 있는 것처럼 동작합니다. `join=\"inner\"`로 설정하면 *양쪽*의 `DataFrame`에 존재하는 열만 반환됩니다:" ] }, { "cell_type": "code", "execution_count": 144, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:29.604735Z", "iopub.status.busy": "2020-10-16T07:31:29.603386Z", "iopub.status.idle": "2020-10-16T07:31:29.609400Z", "shell.execute_reply": "2020-10-16T07:31:29.608131Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
statecity
0CASan Francisco
1NYNew York
2FLMiami
3OHCleveland
4UTSalt Lake City
3CaliforniaSan Francisco
4New-YorkNew York
5FloridaMiami
6TexasHouston
\n", "
" ], "text/plain": [ " state city\n", "0 CA San Francisco\n", "1 NY New York\n", "2 FL Miami\n", "3 OH Cleveland\n", "4 UT Salt Lake City\n", "3 California San Francisco\n", "4 New-York New York\n", "5 Florida Miami\n", "6 Texas Houston" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.concat([city_loc, city_pop], join=\"inner\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`axis=1`로 설정하면 `DataFrame`을 수직이 아니라 수평으로 연결할 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 145, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:29.634308Z", "iopub.status.busy": "2020-10-16T07:31:29.633045Z", "iopub.status.idle": "2020-10-16T07:31:29.639806Z", "shell.execute_reply": "2020-10-16T07:31:29.638758Z" }, "scrolled": true }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
statecitylatlngpopulationcitystate
0CASan Francisco37.781334-122.416728NaNNaNNaN
1NYNew York40.705649-74.008344NaNNaNNaN
2FLMiami25.791100-80.320733NaNNaNNaN
3OHCleveland41.473508-81.739791808976.0San FranciscoCalifornia
4UTSalt Lake City40.755851-111.8966578363710.0New YorkNew-York
5NaNNaNNaNNaN413201.0MiamiFlorida
6NaNNaNNaNNaN2242193.0HoustonTexas
\n", "
" ], "text/plain": [ " state city lat lng population city \\\n", "0 CA San Francisco 37.781334 -122.416728 NaN NaN \n", "1 NY New York 40.705649 -74.008344 NaN NaN \n", "2 FL Miami 25.791100 -80.320733 NaN NaN \n", "3 OH Cleveland 41.473508 -81.739791 808976.0 San Francisco \n", "4 UT Salt Lake City 40.755851 -111.896657 8363710.0 New York \n", "5 NaN NaN NaN NaN 413201.0 Miami \n", "6 NaN NaN NaN NaN 2242193.0 Houston \n", "\n", " state \n", "0 NaN \n", "1 NaN \n", "2 NaN \n", "3 California \n", "4 New-York \n", "5 Florida \n", "6 Texas " ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.concat([city_loc, city_pop], axis=1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "이 경우 인덱스가 잘 정렬되지 않기 때문에 의미가 없습니다(예를 들어 Cleveland와 San Francisco의 인덱스 레이블이 `3`이기 때문에 동일한 행에 놓여 있습니다). 이 `DataFrame`을 연결하기 전에 도시로 인덱스를 재설정해 보죠:" ] }, { "cell_type": "code", "execution_count": 146, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:29.667789Z", "iopub.status.busy": "2020-10-16T07:31:29.648474Z", "iopub.status.idle": "2020-10-16T07:31:29.674949Z", "shell.execute_reply": "2020-10-16T07:31:29.673620Z" }, "scrolled": true }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
statelatlngpopulationstate
San FranciscoCA37.781334-122.416728808976.0California
New YorkNY40.705649-74.0083448363710.0New-York
MiamiFL25.791100-80.320733413201.0Florida
ClevelandOH41.473508-81.739791NaNNaN
Salt Lake CityUT40.755851-111.896657NaNNaN
HoustonNaNNaNNaN2242193.0Texas
\n", "
" ], "text/plain": [ " state lat lng population state\n", "San Francisco CA 37.781334 -122.416728 808976.0 California\n", "New York NY 40.705649 -74.008344 8363710.0 New-York\n", "Miami FL 25.791100 -80.320733 413201.0 Florida\n", "Cleveland OH 41.473508 -81.739791 NaN NaN\n", "Salt Lake City UT 40.755851 -111.896657 NaN NaN\n", "Houston NaN NaN NaN 2242193.0 Texas" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.concat([city_loc.set_index(\"city\"), city_pop.set_index(\"city\")], axis=1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`FULL OUTER JOIN`을 수행한 것과 비슷합니다. 하지만 `state` 열이 `state_x`와 `state_y`로 바뀌지 않았고 `city` 열이 인덱스가 되었습니다." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`append()` 메서드는 `DataFrame`을 수직으로 연결하는 단축 메서드입니다:" ] }, { "cell_type": "code", "execution_count": 147, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:29.698488Z", "iopub.status.busy": "2020-10-16T07:31:29.697097Z", "iopub.status.idle": "2020-10-16T07:31:29.703373Z", "shell.execute_reply": "2020-10-16T07:31:29.702208Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
statecitylatlngpopulation
0CASan Francisco37.781334-122.416728NaN
1NYNew York40.705649-74.008344NaN
2FLMiami25.791100-80.320733NaN
3OHCleveland41.473508-81.739791NaN
4UTSalt Lake City40.755851-111.896657NaN
3CaliforniaSan FranciscoNaNNaN808976.0
4New-YorkNew YorkNaNNaN8363710.0
5FloridaMiamiNaNNaN413201.0
6TexasHoustonNaNNaN2242193.0
\n", "
" ], "text/plain": [ " state city lat lng population\n", "0 CA San Francisco 37.781334 -122.416728 NaN\n", "1 NY New York 40.705649 -74.008344 NaN\n", "2 FL Miami 25.791100 -80.320733 NaN\n", "3 OH Cleveland 41.473508 -81.739791 NaN\n", "4 UT Salt Lake City 40.755851 -111.896657 NaN\n", "3 California San Francisco NaN NaN 808976.0\n", "4 New-York New York NaN NaN 8363710.0\n", "5 Florida Miami NaN NaN 413201.0\n", "6 Texas Houston NaN NaN 2242193.0" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "city_loc.append(city_pop)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "판다스의 다른 메서드와 마찬가지로 `append()` 메서드는 실제 `city_loc`을 수정하지 않습니다. 복사본을 만들어 수정한 다음 반환합니다." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 범주\n", "\n", "범주로 표현된 값을 가진 경우가 흔합니다. 예를 들어 `1`은 여성, `2`는 남성이거나 `\"A\"`는 좋은 것, `\"B\"`는 평균, `\"C\"`는 나쁜 것 등입니다. 범주형 값을 읽기 힘들고 다루기 번거롭습니다. 하지만 판다스에서는 간단합니다. 예를 들기 위해 앞서 만든 `city_pop` `DataFrame`에 범주를 표현하는 열을 추가해 보겠습니다:" ] }, { "cell_type": "code", "execution_count": 148, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:29.721192Z", "iopub.status.busy": "2020-10-16T07:31:29.719801Z", "iopub.status.idle": "2020-10-16T07:31:29.725933Z", "shell.execute_reply": "2020-10-16T07:31:29.724844Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
populationcitystateeco_code
3808976San FranciscoCalifornia17
48363710New YorkNew-York17
5413201MiamiFlorida34
62242193HoustonTexas20
\n", "
" ], "text/plain": [ " population city state eco_code\n", "3 808976 San Francisco California 17\n", "4 8363710 New York New-York 17\n", "5 413201 Miami Florida 34\n", "6 2242193 Houston Texas 20" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "city_eco = city_pop.copy()\n", "city_eco[\"eco_code\"] = [17, 17, 34, 20]\n", "city_eco" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "이제 `eco_code`열은 의미없는 코드입니다. 이를 바꿔 보죠. 먼저 `eco_code`를 기반으로 새로운 범주형 열을 만듭니다:" ] }, { "cell_type": "code", "execution_count": 149, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:29.736341Z", "iopub.status.busy": "2020-10-16T07:31:29.735087Z", "iopub.status.idle": "2020-10-16T07:31:29.740551Z", "shell.execute_reply": "2020-10-16T07:31:29.739607Z" } }, "outputs": [ { "data": { "text/plain": [ "Int64Index([17, 20, 34], dtype='int64')" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "city_eco[\"economy\"] = city_eco[\"eco_code\"].astype('category')\n", "city_eco[\"economy\"].cat.categories" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "의미있는 이름을 가진 범주를 지정할 수 있습니다:" ] }, { "cell_type": "code", "execution_count": 150, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:29.762234Z", "iopub.status.busy": "2020-10-16T07:31:29.760867Z", "iopub.status.idle": "2020-10-16T07:31:29.767647Z", "shell.execute_reply": "2020-10-16T07:31:29.766196Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
populationcitystateeco_codeeconomy
3808976San FranciscoCalifornia17Finance
48363710New YorkNew-York17Finance
5413201MiamiFlorida34Tourism
62242193HoustonTexas20Energy
\n", "
" ], "text/plain": [ " population city state eco_code economy\n", "3 808976 San Francisco California 17 Finance\n", "4 8363710 New York New-York 17 Finance\n", "5 413201 Miami Florida 34 Tourism\n", "6 2242193 Houston Texas 20 Energy" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "city_eco[\"economy\"].cat.categories = [\"Finance\", \"Energy\", \"Tourism\"]\n", "city_eco" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "범주형 값은 알파벳 순서가 아니라 범주형 순서로 정렬합니다:" ] }, { "cell_type": "code", "execution_count": 151, "metadata": { "execution": { "iopub.execute_input": "2020-10-16T07:31:29.788100Z", "iopub.status.busy": "2020-10-16T07:31:29.786648Z", "iopub.status.idle": "2020-10-16T07:31:29.792669Z", "shell.execute_reply": "2020-10-16T07:31:29.791639Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
populationcitystateeco_codeeconomy
5413201MiamiFlorida34Tourism
62242193HoustonTexas20Energy
3808976San FranciscoCalifornia17Finance
48363710New YorkNew-York17Finance
\n", "
" ], "text/plain": [ " population city state eco_code economy\n", "5 413201 Miami Florida 34 Tourism\n", "6 2242193 Houston Texas 20 Energy\n", "3 808976 San Francisco California 17 Finance\n", "4 8363710 New York New-York 17 Finance" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "city_eco.sort_values(by=\"economy\", ascending=False)" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "# 그 다음엔?\n", "\n", "이제 알았겠지만 판다스는 매우 커다란 라이브러리이고 기능이 많습니다. 가장 중요한 기능들을 둘러 보았지만 빙산의 일각일 뿐입니다. 더 많은 것을 익히려면 실전 데이터로 직접 실습해 보는 것이 제일 좋습니다. 판다스의 훌륭한 [문서](http://pandas.pydata.org/pandas-docs/stable/index.html)와 [쿡북](http://pandas.pydata.org/pandas-docs/stable/cookbook.html)을 보는 것도 좋습니다." ] } ], "metadata": { "kernelspec": { "display_name": "TensorFlow 2.4 on Python 3.8 & CUDA 11.1", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.7" }, "toc": { "toc_cell": false, "toc_number_sections": true, "toc_section_display": "none", "toc_threshold": 6, "toc_window_display": true } }, "nbformat": 4, "nbformat_minor": 1 }