{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 07wk-2: Pandas – `pivot_table`, `groupby`+`agg`\n", "\n", "최규빈 \n", "2023-10-16\n", "\n", "\n", "\n", "# 1. 강의영상\n", "\n", "\n", "\n", "# 2. Imports" ], "id": "25926a95-f0f2-4e4a-9ec6-76e3cbe3cb2b" }, { "cell_type": "code", "execution_count": 138, "metadata": { "tags": [] }, "outputs": [], "source": [ "import pandas as pd \n", "import numpy as np" ], "id": "cell-5" }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 3. pivot_table, groupby+agg\n", "\n", "## A. intro\n", "\n", "`-` 개념: 그룹화 $\\to$ 집계\n", "\n", "`# 예제1`: 아래의 예제에서 (학과,성별)로 count의 합계를 구하라." ], "id": "13035ce9-6479-445c-8292-2e1164ac74e0" }, { "cell_type": "code", "execution_count": 139, "metadata": { "tags": [] }, "outputs": [], "source": [ "df=pd.read_csv(\"https://raw.githubusercontent.com/guebin/DV2022/master/posts/Simpson.csv\",index_col=0,header=[0,1])\\\n", ".stack().stack().reset_index()\\\n", ".rename({'level_0':'department','level_1':'result','level_2':'gender',0:'count'},axis=1)\n", "df" ], "id": "cell-10" }, { "cell_type": "code", "execution_count": 140, "metadata": { "tags": [] }, "outputs": [], "source": [ "df.pivot_table(index=['department','gender'],values='count',aggfunc='sum')" ], "id": "cell-11" }, { "cell_type": "markdown", "metadata": {}, "source": [ "`#`\n", "\n", "`-` 예시에서 본 작업은 아래의 작업들로 세분화 할 수 있다.\n", "\n", "1. 그룹화(쿼리): 하나의 dataframe을 sub-dataframe으로 나누는 과정 –\n", " 전체자료를 (학과,성별)로 묶어 총 10개의 sub-dataframe을 만듦\n", "2. 각각집계(각각계산): 나누어진 sub-dataframe에서 어떠한 계산을 각각\n", " 수행함. – 나누어진 sub-dataframe에서 지원자수의 합계를 각각 구함\n", "\n", "`-` 위의 같은 작업을 하려면 아래와 같은 요소들이 필요하다.\n", "\n", "1. 그룹변수[1] – 그룹화를 위해 필요한 변수, dataframe을\n", " sub-dataframe으로 나누는 역할.\n", "2. 집계변수[2] – 집계함수의 대상이 되는 변수.\n", "3. 집계변수 – 그룹화된 데이터프레임에 수행하는 계산을 정의하는 함수.\n", "\n", "## B. `pivot_table`의 문법\n", "\n", "`-` pivot_table의 문법\n", "\n", "``` python\n", "df.pivot_table(\n", " index = 그룹변수\n", " colums = 그룹변수 \n", " values = 집계변수\n", " aggfunc = 집계함수\n", ")\n", "```\n", "\n", "`-` 그룹변수: string, 혹은 list of string 으로 전달한다.\n", "\n", "- 예시: ‘department’, \\[‘department’\\], \\[‘department’,‘gender’\\]\n", "\n", "`-` 집계변수: string, 혹은 list of string 으로 전달한다.\n", "\n", "- 예시: ‘CANCELLED’, \\[‘CANCELLED’\\], \\[‘CANCELLED’,‘AIR_TIME’\\]\n", "\n", "`-` 집계함수: 함수자체[3]를 전달하거나, 함수를 의미하는 문자열[4], 혹은\n", "그것들의 리스트형태로 전달한다.\n", "\n", "`# 예시`: 집계합수를 전달하는 방법\n", "\n", "**data**\n", "\n", "[1] 이건 없는 용어에요\n", "\n", "[2] 이것도 없는 용어에요\n", "\n", "[3] `np.mean`,`sum`\n", "\n", "[4] ‘count’, ‘sum’, ‘mean’, ‘median’, ‘min’, ‘max’, ‘std’, ‘var’" ], "id": "35bd294c-b144-4686-8f4e-18e4f1714b21" }, { "cell_type": "code", "execution_count": 141, "metadata": { "tags": [] }, "outputs": [], "source": [ "df = pd.DataFrame({'category':['A']*5+['B']*5, 'value':np.concatenate([np.random.randn(5), np.random.randn(5)+10])})\n", "df" ], "id": "cell-23" }, { "cell_type": "markdown", "metadata": {}, "source": [ "**방법1** – 함수자체를 전달" ], "id": "3e95d4fc-6d61-4d4e-ba68-71bd19bcef6f" }, { "cell_type": "code", "execution_count": 142, "metadata": { "tags": [] }, "outputs": [ { "output_type": "stream", "name": "stderr", "text": [ "/tmp/ipykernel_3437616/3923531937.py:1: FutureWarning: The provided callable is currently using DataFrameGroupBy.sum. In a future version of pandas, the provided callable will be used directly. To keep current behavior pass the string \"sum\" instead.\n", " df.pivot_table(index=['category'],values='value',aggfunc=np.sum) # 함수자체" ] } ], "source": [ "df.pivot_table(index=['category'],values='value',aggfunc=np.sum) # 함수자체" ], "id": "cell-25" }, { "cell_type": "markdown", "metadata": {}, "source": [ "**방법2** – 함수를 의미하는 문자열을 전달" ], "id": "b92dadda-b2bf-4e58-a9cd-e48b7647d8ee" }, { "cell_type": "code", "execution_count": 143, "metadata": { "tags": [] }, "outputs": [], "source": [ "df.pivot_table(index=['category'],values='value',aggfunc='sum') # 리스트" ], "id": "cell-27" }, { "cell_type": "markdown", "metadata": {}, "source": [ "**방법3** – 리스트를 전달" ], "id": "7e1d6ae4-b5d7-4288-8b5c-b376ad9d29f6" }, { "cell_type": "code", "execution_count": 144, "metadata": { "tags": [] }, "outputs": [ { "output_type": "stream", "name": "stderr", "text": [ "/tmp/ipykernel_3437616/1880687379.py:1: FutureWarning: The provided callable is currently using DataFrameGroupBy.mean. In a future version of pandas, the provided callable will be used directly. To keep current behavior pass the string \"mean\" instead.\n", " df.pivot_table(\n", "/tmp/ipykernel_3437616/1880687379.py:1: FutureWarning: The provided callable is currently using DataFrameGroupBy.max. In a future version of pandas, the provided callable will be used directly. To keep current behavior pass the string \"max\" instead.\n", " df.pivot_table(" ] } ], "source": [ "df.pivot_table(\n", " index=['category'],\n", " values='value',\n", " aggfunc=['sum','min',np.mean,np.max,'count']\n", ")" ], "id": "cell-29" }, { "cell_type": "markdown", "metadata": {}, "source": [ "## C. `groupby` + `aggregate` 의 문법\n", "\n", "`-` groupby + aggregate 의 문법\n", "\n", "``` python\n", "df.groupby(그룹변수).aggregate({집계변수:집계함수})\n", "```\n", "\n", "# 4. AIRLINE 자료로 연습" ], "id": "974afe7c-730f-4f95-9327-59c924212085" }, { "cell_type": "code", "execution_count": 145, "metadata": { "tags": [] }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "\n", "RangeIndex: 58492 entries, 0 to 58491\n", "Data columns (total 14 columns):\n", " # Column Non-Null Count Dtype \n", "--- ------ -------------- ----- \n", " 0 MONTH 58492 non-null int64 \n", " 1 DAY 58492 non-null int64 \n", " 2 WEEKDAY 58492 non-null int64 \n", " 3 AIRLINE 58492 non-null object \n", " 4 ORG_AIR 58492 non-null object \n", " 5 DEST_AIR 58492 non-null object \n", " 6 SCHED_DEP 58492 non-null int64 \n", " 7 DEP_DELAY 57659 non-null float64\n", " 8 AIR_TIME 57474 non-null float64\n", " 9 DIST 58492 non-null int64 \n", " 10 SCHED_ARR 58492 non-null int64 \n", " 11 ARR_DELAY 57474 non-null float64\n", " 12 DIVERTED 58492 non-null int64 \n", " 13 CANCELLED 58492 non-null int64 \n", "dtypes: float64(3), int64(8), object(3)\n", "memory usage: 6.2+ MB" ] } ], "source": [ "df=pd.read_csv('https://raw.githubusercontent.com/PacktPublishing/Pandas-Cookbook/master/data/flights.csv')\n", "df.info()" ], "id": "cell-33" }, { "cell_type": "markdown", "metadata": {}, "source": [ "`-` 각 변수들에 대한 설명은 아래와 같다. (ChatGPT의 도움을 받아 정리함)\n", "\n", "1. `MONTH`: 비행이 이루어진 월을 나타냄. 1에서 12 사이의 값을 갖음.\n", "2. `DAY`: 비행이 이루어진 일자를 나타냄. 월에 따라 1~28/29/30/31 사이의\n", " 값을 가질 수 있음.\n", "3. `WEEKDAY`: 비행이 이루어진 요일을 나타냄. 일반적으로 1(일요일)부터\n", " 7(토요일)까지의 값을 갖음.\n", "4. `AIRLINE`: 해당 항공편을 운영하는 항공사의 약어나 코드를 나타냄.\n", "5. `ORG_AIR`: 비행기가 출발하는 공항의 약어나 코드를 나타냄.\n", "6. `DEST_AIR`: 비행기가 도착하는 공항의 약어나 코드를 나타냄.\n", "7. `SCHED_DEP`: 원래의 예정된 출발 시간을 나타냄. 시간은 일반적으로\n", " HHMM 형식으로 표시될 수 있음.\n", "8. `DEP_DELAY`: 출발 지연 시간을 나타냄. 음수 값은 조기 출발, 양수 값은\n", " 지연을 의미함.\n", "9. `AIR_TIME`: 실제 공중에서 비행한 시간을 분 단위로 나타냄.\n", "10. `DIST`: 비행 거리를 나타냄. 일반적으로 마일 또는 킬로미터로 표시됨.\n", "11. `SCHED_ARR`: 원래의 예정된 도착 시간을 나타냄. `SCHED_DEP`와 같은\n", " 형식으로 표시될 수 있음.\n", "12. `ARR_DELAY`: 도착 지연 시간을 나타냄. 음수는 조기 도착, 양수는\n", " 지연을 의미함.\n", "13. `DIVERTED`: 항공편이 다른 곳으로 우회되었는지를 나타냄. 1은 우회,\n", " 0은 정상 경로를 의미함.\n", "14. `CANCELLED`: 항공편이 취소되었는지 여부를 나타냄. 1은 취소, 0은\n", " 취소되지 않음을 의미함.\n", "\n", "`# 예제1`: 항공사별로 도착지연시간의 평균을 구하라.\n", "\n", "`-` 풀이1" ], "id": "28b5e3fd-7a4d-4bde-a636-78a9625615ff" }, { "cell_type": "code", "execution_count": 146, "metadata": { "tags": [] }, "outputs": [], "source": [ "df.pivot_table(index='AIRLINE',values='ARR_DELAY')" ], "id": "cell-37" }, { "cell_type": "markdown", "metadata": {}, "source": [ "`-` 풀이2" ], "id": "ef061a5b-13ec-4d9a-b540-67042218611e" }, { "cell_type": "code", "execution_count": 147, "metadata": { "tags": [] }, "outputs": [ { "output_type": "stream", "name": "stderr", "text": [ "/tmp/ipykernel_3437616/4188396604.py:1: FutureWarning: The provided callable is currently using SeriesGroupBy.mean. In a future version of pandas, the provided callable will be used directly. To keep current behavior pass the string \"mean\" instead.\n", " df.groupby(by=\"AIRLINE\").aggregate({'ARR_DELAY':np.mean})" ] } ], "source": [ "df.groupby(by=\"AIRLINE\").aggregate({'ARR_DELAY':np.mean})" ], "id": "cell-39" }, { "cell_type": "markdown", "metadata": {}, "source": [ "`#`\n", "\n", "`# 예제2`: 항공사별로 비행취소건수의 합계를 구하라. 취소건수가 높은\n", "항공사순으로 정렬하라.\n", "\n", "`-` 풀이1: `.pivot_table()`을 이용" ], "id": "49e1c599-6b5a-494e-80b7-1827efd4c872" }, { "cell_type": "code", "execution_count": 148, "metadata": { "tags": [] }, "outputs": [], "source": [ "df.pivot_table(index='AIRLINE',values='CANCELLED',aggfunc='sum').sort_values('CANCELLED',ascending=False)" ], "id": "cell-43" }, { "cell_type": "markdown", "metadata": {}, "source": [ "`-` 풀이2: `.groupby()`+`.aggregate()`를 이용" ], "id": "1357baf5-7c29-45a3-86be-f38d8b8caef9" }, { "cell_type": "code", "execution_count": 149, "metadata": { "tags": [] }, "outputs": [], "source": [ "df.groupby('AIRLINE').aggregate({'CANCELLED':'sum'}).sort_values('CANCELLED',ascending=False)" ], "id": "cell-45" }, { "cell_type": "markdown", "metadata": {}, "source": [ "`# 예제3`: 항공사별로 비행취소율을 구하라. 비행취소율이 가장 높은 항공사\n", "순으로 정렬하라.\n", "\n", "`-` 풀이1: `.pivot_table()`을 이용" ], "id": "ae6583bb-72f1-4f62-90dd-2e99e5acb6cf" }, { "cell_type": "code", "execution_count": 150, "metadata": { "tags": [] }, "outputs": [], "source": [ "df.pivot_table(index='AIRLINE',values='CANCELLED',aggfunc='mean').sort_values('CANCELLED',ascending=False)" ], "id": "cell-48" }, { "cell_type": "markdown", "metadata": {}, "source": [ "`-` 풀이2: `.groupby()`+`.aggregate()`를 이용" ], "id": "2aa2c3df-f429-4a9a-96bc-b74ca1b5bb79" }, { "cell_type": "code", "execution_count": 151, "metadata": { "tags": [] }, "outputs": [], "source": [ "df.groupby('AIRLINE').aggregate({'CANCELLED':'mean'}).sort_values('CANCELLED',ascending=False)" ], "id": "cell-50" }, { "cell_type": "markdown", "metadata": {}, "source": [ "`# 예제4` (항공사,요일)별 비행취소건수와 비행취소율을 조사하라.\n", "\n", "`-` 풀이1: `.pivot_table()`을 이용" ], "id": "5118fab3-10a8-4759-8537-62313160f378" }, { "cell_type": "code", "execution_count": 152, "metadata": { "tags": [] }, "outputs": [ { "output_type": "stream", "name": "stderr", "text": [ "/tmp/ipykernel_3437616/757677508.py:1: FutureWarning: The provided callable is currently using DataFrameGroupBy.mean. In a future version of pandas, the provided callable will be used directly. To keep current behavior pass the string \"mean\" instead.\n", " df.pivot_table(index=['AIRLINE','WEEKDAY'],values='CANCELLED',aggfunc=[np.mean,sum])\n", "/tmp/ipykernel_3437616/757677508.py:1: FutureWarning: The provided callable is currently using DataFrameGroupBy.sum. In a future version of pandas, the provided callable will be used directly. To keep current behavior pass the string \"sum\" instead.\n", " df.pivot_table(index=['AIRLINE','WEEKDAY'],values='CANCELLED',aggfunc=[np.mean,sum])" ] } ], "source": [ "df.pivot_table(index=['AIRLINE','WEEKDAY'],values='CANCELLED',aggfunc=[np.mean,sum])" ], "id": "cell-53" }, { "cell_type": "markdown", "metadata": {}, "source": [ "`-` 풀이2: `.groupby()`+`.aggregate()`를 이용" ], "id": "db6f69a3-59ba-461c-882d-814c9d5d9c28" }, { "cell_type": "code", "execution_count": 153, "metadata": { "tags": [] }, "outputs": [ { "output_type": "stream", "name": "stderr", "text": [ "/tmp/ipykernel_3437616/1354178761.py:1: FutureWarning: The provided callable is currently using SeriesGroupBy.mean. In a future version of pandas, the provided callable will be used directly. To keep current behavior pass the string \"mean\" instead.\n", " df.groupby(['AIRLINE','WEEKDAY']).aggregate({'CANCELLED':[np.mean,sum]})\n", "/tmp/ipykernel_3437616/1354178761.py:1: FutureWarning: The provided callable is currently using SeriesGroupBy.sum. In a future version of pandas, the provided callable will be used directly. To keep current behavior pass the string \"sum\" instead.\n", " df.groupby(['AIRLINE','WEEKDAY']).aggregate({'CANCELLED':[np.mean,sum]})" ] } ], "source": [ "df.groupby(['AIRLINE','WEEKDAY']).aggregate({'CANCELLED':[np.mean,sum]})" ], "id": "cell-55" }, { "cell_type": "markdown", "metadata": {}, "source": [ "`# 예제4`: (항공사,요일)별로 `CANCELLED`는 평균과 합계를 구하고 (즉\n", "비행취소건수와 취소율을 구하고), `AIR_TIME`은 평균과 표준편차를\n", "구하여라.\n", "\n", "`-` 풀이1: `.pivot_table()` –\\> 이거 제가 수업할때는 못한다고 했는데\n", "찾아보니까 아래처럼 할 수 있습니다." ], "id": "2de13da7-ba0b-420d-b711-e00487b051ac" }, { "cell_type": "code", "execution_count": 160, "metadata": { "tags": [] }, "outputs": [ { "output_type": "stream", "name": "stderr", "text": [ "/tmp/ipykernel_3437616/2860571331.py:1: FutureWarning: The provided callable is currently using SeriesGroupBy.mean. In a future version of pandas, the provided callable will be used directly. To keep current behavior pass the string \"mean\" instead.\n", " df.pivot_table(\n", "/tmp/ipykernel_3437616/2860571331.py:1: FutureWarning: The provided callable is currently using SeriesGroupBy.sum. In a future version of pandas, the provided callable will be used directly. To keep current behavior pass the string \"sum\" instead.\n", " df.pivot_table(" ] } ], "source": [ "df.pivot_table(\n", " index=['AIRLINE', 'WEEKDAY'],\n", " aggfunc={'CANCELLED': [np.mean, sum], 'AIR_TIME': ['mean','std']}\n", ")" ], "id": "cell-58" }, { "cell_type": "markdown", "metadata": {}, "source": [ "`-` 풀이2: `.groupby()`+`.aggregate()`를 이용" ], "id": "228c7511-dc36-44fa-b134-4c1c5bb2cea4" }, { "cell_type": "code", "execution_count": 161, "metadata": { "tags": [] }, "outputs": [ { "output_type": "stream", "name": "stderr", "text": [ "/tmp/ipykernel_3437616/2787668343.py:2: FutureWarning: The provided callable is currently using SeriesGroupBy.mean. In a future version of pandas, the provided callable will be used directly. To keep current behavior pass the string \"mean\" instead.\n", " .aggregate({'CANCELLED': [np.mean,sum],'AIR_TIME': ['mean','std']})\n", "/tmp/ipykernel_3437616/2787668343.py:2: FutureWarning: The provided callable is currently using SeriesGroupBy.sum. In a future version of pandas, the provided callable will be used directly. To keep current behavior pass the string \"sum\" instead.\n", " .aggregate({'CANCELLED': [np.mean,sum],'AIR_TIME': ['mean','std']})" ] } ], "source": [ "df.groupby(['AIRLINE','WEEKDAY'])\\\n", ".aggregate({'CANCELLED': [np.mean,sum],'AIR_TIME': ['mean','std']})" ], "id": "cell-60" }, { "cell_type": "markdown", "metadata": {}, "source": [ "`#`\n", "\n", "`# 예제5`: 운행구간을 그룹화하고, 운행구간별 비행취소건수와 취소율을\n", "구하여라.\n", "\n", "`-` 풀이1" ], "id": "d50e93f2-34c6-44d3-bcd7-70a39fd8530a" }, { "cell_type": "code", "execution_count": 156, "metadata": { "tags": [] }, "outputs": [], "source": [ "df.assign(DIST_CUT= pd.qcut(df.DIST,q=4)).pivot_table(\n", " index= ['DIST_CUT'],\n", " values= 'CANCELLED',\n", " aggfunc= ['mean','sum']\n", ")" ], "id": "cell-64" }, { "cell_type": "markdown", "metadata": {}, "source": [ "`-` 풀이2" ], "id": "ab1a7ce1-1195-46fa-809d-863d9d8c5e73" }, { "cell_type": "code", "execution_count": 157, "metadata": { "tags": [] }, "outputs": [ { "output_type": "stream", "name": "stderr", "text": [ "/tmp/ipykernel_3437616/402182245.py:2: FutureWarning: The default of observed=False is deprecated and will be changed to True in a future version of pandas. Pass observed=False to retain current behavior or observed=True to adopt the future default and silence this warning.\n", " .groupby('DIST_CUT')\\" ] } ], "source": [ "df.assign(DIST_CUT= pd.qcut(df.DIST,q=4))\\\n", ".groupby('DIST_CUT')\\\n", ".aggregate({'CANCELLED':['mean','sum']})" ], "id": "cell-66" }, { "cell_type": "markdown", "metadata": {}, "source": [ "`#`\n", "\n", "# 5. HW" ], "id": "68d580b2-6800-4f3b-9ba2-c9690d703173" }, { "cell_type": "code", "execution_count": 172, "metadata": { "tags": [] }, "outputs": [], "source": [ "np.random.seed(43052)\n", "df = pd.DataFrame({'X1':['A']*5+['B']*5, 'X2':np.concatenate([np.random.randn(5), np.random.randn(5)+10])})\n", "df" ], "id": "cell-69" }, { "cell_type": "markdown", "metadata": {}, "source": [ "위의 자료에서 X1을 기준으로 그룹화한뒤 X2에 대하여 아래의 함수를\n", "적용하라.\n", "\n", "$$\\max(\\text{X2})-\\min(\\text{X2})$$\n", "\n", "출력결과는 아래와 같아야 한다 ." ], "id": "80dbc91a-482c-42da-a0bb-a6d6df10bd63" }, { "cell_type": "code", "execution_count": 166, "metadata": { "tags": [] }, "outputs": [], "source": [ "# " ], "id": "cell-72" } ], "nbformat": 4, "nbformat_minor": 5, "metadata": { "kernelspec": { "name": "python3", "display_name": "Python 3 (ipykernel)", "language": "python" }, "language_info": { "name": "python", "codemirror_mode": { "name": "ipython", "version": "3" }, "file_extension": ".py", "mimetype": "text/x-python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.13" } } }