{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "2419a897",
   "metadata": {},
   "source": [
    "# 3. Pandas Series 기초\n",
    "\n",
    "## 📚 학습 목표\n",
    "- Pandas Series의 기본 개념과 구조 이해\n",
    "- Series 생성 및 조작 방법 습득\n",
    "- Series 인덱싱과 슬라이싱 활용\n",
    "- Series 연산과 메서드 사용법 익히기\n",
    "\n",
    "## 🔍 문제 설명\n",
    "\n",
    "Pandas Series는 1차원 라벨링된 배열로, 인덱스와 값의 쌍으로 구성됩니다. DataFrame의 기본 구성 요소이며, 데이터 분석에서 매우 중요한 역할을 합니다.\n",
    "\n",
    "### 실전 활용 사례\n",
    "- **시계열 데이터**: 주가, 온도, 판매량 등의 시간별 데이터\n",
    "- **특성 벡터**: 머신러닝에서 단일 특성 데이터\n",
    "- **통계 분석**: 평균, 분산, 분위수 등의 계산\n",
    "- **데이터 검증**: 데이터 타입과 범위 확인\n",
    "\n",
    "## 📝 문제\n",
    "\n",
    "### 문제 3-1: Series 생성\n",
    "1. 1부터 10까지의 숫자로 Series를 생성하고 인덱스를 'A'부터 'J'까지 설정하세요.\n",
    "2. 딕셔너리를 사용하여 Series를 생성하세요.\n",
    "3. 스칼라 값으로 Series를 생성하세요.\n",
    "\n",
    "### 문제 3-2: Series 인덱싱과 슬라이싱\n",
    "4. Series에서 특정 인덱스의 값을 추출하세요.\n",
    "5. 조건부 필터링을 사용하여 짝수 값만 추출하세요.\n",
    "6. 슬라이싱을 사용하여 특정 범위의 값을 추출하세요.\n",
    "\n",
    "### 문제 3-3: Series 연산과 메서드\n",
    "7. Series의 기본 통계 정보를 확인하세요.\n",
    "8. Series에 스칼라 연산을 적용하세요.\n",
    "9. 두 Series 간의 연산을 수행하세요.\n",
    "\n",
    "## 💡 해답 및 설명\n",
    "\n",
    "### 해답 3-1: Series 생성\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "de32c35e",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "\n",
    "# 1. 1부터 10까지의 숫자로 Series 생성하고 인덱스 설정\n",
    "s1 = pd.Series(np.arange(1, 11), index=list('ABCDEFGHIJ'))\n",
    "print(\"Series 1:\")\n",
    "print(s1)\n",
    "print(f\"인덱스: {s1.index}\")\n",
    "print(f\"값: {s1.values}\")\n",
    "print(f\"데이터 타입: {s1.dtype}\")\n",
    "\n",
    "# 2. 딕셔너리를 사용하여 Series 생성\n",
    "data_dict = {'서울': 1000, '부산': 800, '대구': 600, '인천': 900, '광주': 500}\n",
    "s2 = pd.Series(data_dict)\n",
    "print(\"\\nSeries 2 (딕셔너리로 생성):\")\n",
    "print(s2)\n",
    "\n",
    "# 3. 스칼라 값으로 Series 생성\n",
    "scalar_series = pd.Series(5, index=['A', 'B', 'C', 'D', 'E'])\n",
    "print(\"\\nSeries 3 (스칼라 값):\")\n",
    "print(scalar_series)\n",
    "\n",
    "# 추가 생성 방법들\n",
    "print(\"\\n다양한 Series 생성 방법:\")\n",
    "# 리스트로 생성\n",
    "s4 = pd.Series([1, 2, 3, 4, 5])\n",
    "print(\"리스트로 생성:\", s4)\n",
    "\n",
    "# 튜플로 생성\n",
    "s5 = pd.Series((10, 20, 30, 40, 50))\n",
    "print(\"튜플로 생성:\", s5)\n",
    "\n",
    "# NumPy 배열로 생성\n",
    "s6 = pd.Series(np.random.randn(5), index=['a', 'b', 'c', 'd', 'e'])\n",
    "print(\"NumPy 배열로 생성:\", s6)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f4d2c690",
   "metadata": {},
   "source": [
    "\n",
    "\n",
    "### 해답 3-2: Series 인덱싱과 슬라이싱\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e0c815be",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 4. Series에서 특정 인덱스의 값을 추출\n",
    "print(\"특정 인덱스 값 추출:\")\n",
    "print(\"s1['A']:\", s1['A'])  # 라벨 인덱싱\n",
    "print(\"s1[0]:\", s1[0])      # 위치 인덱싱\n",
    "print(\"s1.iloc[2]:\", s1.iloc[2])  # 정수 위치 인덱싱\n",
    "print(\"s1.loc['C']:\", s1.loc['C'])  # 라벨 인덱싱\n",
    "\n",
    "# 5. 조건부 필터링\n",
    "print(\"\\n조건부 필터링:\")\n",
    "even_values = s1[s1 % 2 == 0]\n",
    "print(\"짝수 값만:\", even_values)\n",
    "\n",
    "# 5보다 큰 값만\n",
    "greater_than_5 = s1[s1 > 5]\n",
    "print(\"5보다 큰 값:\", greater_than_5)\n",
    "\n",
    "# 6. 슬라이싱\n",
    "print(\"\\n슬라이싱:\")\n",
    "print(\"s1['A':'E']:\", s1['A':'E'])  # 라벨 슬라이싱 (끝 포함)\n",
    "print(\"s1[0:5]:\", s1[0:5])          # 위치 슬라이싱 (끝 미포함)\n",
    "print(\"s1.iloc[1:4]:\", s1.iloc[1:4])  # 정수 위치 슬라이싱\n",
    "print(\"s1.loc['B':'F']:\", s1.loc['B':'F'])  # 라벨 슬라이싱\n",
    "\n",
    "# 역순 슬라이싱\n",
    "print(\"역순 슬라이싱:\", s1[::-1])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "81906be8",
   "metadata": {},
   "source": [
    "\n",
    "\n",
    "### 해답 3-3: Series 연산과 메서드\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "019e9b84",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 7. Series의 기본 통계 정보\n",
    "print(\"Series 기본 통계 정보:\")\n",
    "print(f\"평균: {s1.mean()}\")\n",
    "print(f\"중앙값: {s1.median()}\")\n",
    "print(f\"표준편차: {s1.std()}\")\n",
    "print(f\"분산: {s1.var()}\")\n",
    "print(f\"최솟값: {s1.min()}\")\n",
    "print(f\"최댓값: {s1.max()}\")\n",
    "print(f\"합계: {s1.sum()}\")\n",
    "print(f\"개수: {s1.count()}\")\n",
    "\n",
    "# describe() 메서드로 한 번에 확인\n",
    "print(\"\\n전체 통계 요약:\")\n",
    "print(s1.describe())\n",
    "\n",
    "# 8. Series에 스칼라 연산 적용\n",
    "print(\"\\n스칼라 연산:\")\n",
    "print(\"원본 Series:\", s1)\n",
    "print(\"2배:\", s1 * 2)\n",
    "print(\"제곱:\", s1 ** 2)\n",
    "print(\"제곱근:\", np.sqrt(s1))\n",
    "print(\"로그:\", np.log(s1))\n",
    "\n",
    "# 9. 두 Series 간의 연산\n",
    "s7 = pd.Series([10, 20, 30, 40, 50], index=['A', 'B', 'C', 'D', 'E'])\n",
    "s8 = pd.Series([1, 2, 3, 4, 5], index=['A', 'B', 'C', 'D', 'E'])\n",
    "\n",
    "print(\"\\n두 Series 간의 연산:\")\n",
    "print(\"s7:\", s7)\n",
    "print(\"s8:\", s8)\n",
    "print(\"덧셈:\", s7 + s8)\n",
    "print(\"뺄셈:\", s7 - s8)\n",
    "print(\"곱셈:\", s7 * s8)\n",
    "print(\"나눗셈:\", s7 / s8)\n",
    "\n",
    "# 인덱스가 다른 경우\n",
    "s9 = pd.Series([1, 2, 3], index=['A', 'B', 'F'])\n",
    "print(\"\\n인덱스가 다른 Series 연산:\")\n",
    "print(\"s7 + s9:\", s7 + s9)  # 공통 인덱스만 연산, 나머지는 NaN"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e7417ff0",
   "metadata": {},
   "source": [
    "\n",
    "\n",
    "## 🔧 주요 Series 메서드와 속성\n",
    "\n",
    "### 기본 속성\n",
    "- `series.index`: 인덱스 객체\n",
    "- `series.values`: 값 배열\n",
    "- `series.dtype`: 데이터 타입\n",
    "- `series.shape`: 형태 (튜플)\n",
    "- `series.size`: 원소 개수\n",
    "\n",
    "### 통계 메서드\n",
    "- `series.mean()`: 평균\n",
    "- `series.median()`: 중앙값\n",
    "- `series.std()`: 표준편차\n",
    "- `series.var()`: 분산\n",
    "- `series.min()`, `series.max()`: 최솟값, 최댓값\n",
    "- `series.sum()`: 합계\n",
    "- `series.count()`: 비NaN 값 개수\n",
    "- `series.describe()`: 통계 요약\n",
    "\n",
    "### 인덱싱 메서드\n",
    "- `series.loc[]`: 라벨 인덱싱\n",
    "- `series.iloc[]`: 정수 위치 인덱싱\n",
    "- `series.at[]`: 단일 라벨 값\n",
    "- `series.iat[]`: 단일 위치 값\n",
    "\n",
    "### 데이터 처리 메서드\n",
    "- `series.isnull()`: NaN 값 확인\n",
    "- `series.notnull()`: 비NaN 값 확인\n",
    "- `series.fillna()`: NaN 값 채우기\n",
    "- `series.dropna()`: NaN 값 제거\n",
    "- `series.unique()`: 고유 값\n",
    "- `series.value_counts()`: 값 빈도\n",
    "\n",
    "## 📊 추가 연습문제\n",
    "\n",
    "### 연습문제 1: Series 생성과 조작\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f602bf53",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 다음 문제들을 풀어보세요:\n",
    "# 1. 월별 평균 온도 데이터를 Series로 생성하세요.\n",
    "#    (1월: -2, 2월: 1, 3월: 7, 4월: 13, 5월: 18, 6월: 23)\n",
    "# 2. 해당 Series에서 봄철(3~5월) 온도만 추출하세요.\n",
    "# 3. 연평균 온도를 계산하세요."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2715aae7",
   "metadata": {},
   "source": [
    "\n",
    "\n",
    "### 연습문제 2: 조건부 필터링\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bf30e7cf",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 다음 Series를 생성하고 문제를 풀어보세요:\n",
    "scores = pd.Series([85, 92, 78, 96, 88, 75, 91, 83, 79, 94], \n",
    "                   index=['학생1', '학생2', '학생3', '학생4', '학생5', \n",
    "                          '학생6', '학생7', '학생8', '학생9', '학생10'])\n",
    "\n",
    "# 1. 90점 이상인 학생들의 점수를 추출하세요.\n",
    "# 2. 평균 점수를 계산하세요.\n",
    "# 3. 표준편차를 계산하세요.\n",
    "# 4. 최고점과 최저점의 차이를 구하세요."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "74dc8f78",
   "metadata": {},
   "source": [
    "\n",
    "\n",
    "### 연습문제 3: Series 연산\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a5b04e03",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 두 개의 Series를 생성하고 연산을 수행해보세요:\n",
    "sales_2022 = pd.Series([100, 120, 90, 150, 80], \n",
    "                       index=['1월', '2월', '3월', '4월', '5월'])\n",
    "sales_2023 = pd.Series([110, 130, 95, 160, 85], \n",
    "                       index=['1월', '2월', '3월', '4월', '5월'])\n",
    "\n",
    "# 1. 2023년 대비 2022년 매출 증가율을 계산하세요.\n",
    "# 2. 두 해의 평균 매출을 비교하세요.\n",
    "# 3. 월별 매출 차이를 계산하세요."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c0310d86",
   "metadata": {},
   "source": [
    "\n",
    "\n",
    "## ⚠️ 주의사항 및 팁\n",
    "\n",
    "1. **인덱스 라벨**: Series의 인덱스는 라벨이므로 문자열로 접근할 때는 `loc`를 사용하는 것이 좋습니다.\n",
    "2. **데이터 타입**: Series는 동일한 데이터 타입을 가져야 하므로, 혼합 타입은 object 타입이 됩니다.\n",
    "3. **NaN 처리**: 연산 결과가 정의되지 않으면 NaN이 반환됩니다.\n",
    "4. **인덱스 정렬**: Series 연산 시 인덱스가 자동으로 정렬됩니다.\n",
    "5. **메모리 효율성**: 큰 데이터셋에서는 적절한 데이터 타입을 선택하는 것이 중요합니다.\n",
    "\n",
    "## 🎯 실전 활용 예제\n",
    "\n",
    "### 예제 1: 주식 가격 분석\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7dbfeb36",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 일별 주식 가격 데이터\n",
    "np.random.seed(42)\n",
    "dates = pd.date_range('2023-01-01', periods=30, freq='D')\n",
    "stock_prices = pd.Series(np.random.normal(100, 5, 30).cumsum(), index=dates)\n",
    "\n",
    "print(\"주식 가격 데이터:\")\n",
    "print(stock_prices.head())\n",
    "\n",
    "# 수익률 계산\n",
    "returns = stock_prices.pct_change()\n",
    "print(\"\\n일별 수익률:\")\n",
    "print(returns.head())\n",
    "\n",
    "# 통계 정보\n",
    "print(f\"\\n평균 수익률: {returns.mean():.4f}\")\n",
    "print(f\"수익률 표준편차: {returns.std():.4f}\")\n",
    "print(f\"최고 수익률: {returns.max():.4f}\")\n",
    "print(f\"최저 수익률: {returns.min():.4f}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cb82a9b6",
   "metadata": {},
   "source": [
    "\n",
    "\n",
    "### 예제 2: 온도 데이터 분석\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "470822fb",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 월별 평균 온도 데이터\n",
    "temperatures = pd.Series([-2, 1, 7, 13, 18, 23, 26, 25, 20, 13, 6, 0],\n",
    "                        index=['1월', '2월', '3월', '4월', '5월', '6월',\n",
    "                               '7월', '8월', '9월', '10월', '11월', '12월'])\n",
    "\n",
    "print(\"월별 평균 온도:\")\n",
    "print(temperatures)\n",
    "\n",
    "# 계절별 온도 분석\n",
    "spring = temperatures[['3월', '4월', '5월']]\n",
    "summer = temperatures[['6월', '7월', '8월']]\n",
    "autumn = temperatures[['9월', '10월', '11월']]\n",
    "winter = temperatures[['12월', '1월', '2월']]\n",
    "\n",
    "print(f\"\\n봄 평균 온도: {spring.mean():.1f}°C\")\n",
    "print(f\"여름 평균 온도: {summer.mean():.1f}°C\")\n",
    "print(f\"가을 평균 온도: {autumn.mean():.1f}°C\")\n",
    "print(f\"겨울 평균 온도: {winter.mean():.1f}°C\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b8e7c464",
   "metadata": {},
   "source": [
    "\n",
    "\n",
    "### 예제 3: 판매 데이터 분석\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3e85f81c",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 제품별 판매량 데이터\n",
    "sales_data = pd.Series([150, 200, 120, 300, 180, 250, 90, 160, 220, 140],\n",
    "                       index=['노트북', '스마트폰', '태블릿', '이어폰', '스마트워치',\n",
    "                              '키보드', '마우스', '모니터', '프린터', '스피커'])\n",
    "\n",
    "print(\"제품별 판매량:\")\n",
    "print(sales_data)\n",
    "\n",
    "# 판매량 기준 정렬\n",
    "sorted_sales = sales_data.sort_values(ascending=False)\n",
    "print(\"\\n판매량 순으로 정렬:\")\n",
    "print(sorted_sales)\n",
    "\n",
    "# 상위 5개 제품\n",
    "top_5 = sorted_sales.head()\n",
    "print(f\"\\n상위 5개 제품 총 판매량: {top_5.sum()}개\")\n",
    "\n",
    "# 평균 판매량 대비 성과\n",
    "performance = sales_data / sales_data.mean()\n",
    "print(\"\\n평균 대비 판매 성과:\")\n",
    "print(performance)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6703f537",
   "metadata": {},
   "source": [
    "\n",
    "\n",
    "## 📚 다음 단계\n",
    "\n",
    "이제 Pandas Series의 기본을 익혔습니다. 다음 단계에서는:\n",
    "- DataFrame 생성과 기초 조작\n",
    "- 데이터 인덱싱, 슬라이싱, 필터링\n",
    "- 결측치 처리와 데이터 정제\n",
    "- 그룹화와 집계\n",
    "\n",
    "을 학습하게 됩니다.\n",
    "\n",
    "---\n",
    "\n",
    "**참고 자료:**\n",
    "- [Pandas Series 공식 문서](https://pandas.pydata.org/docs/reference/api/pandas.Series.html)\n",
    "- [Pandas Series 튜토리얼](https://pandas.pydata.org/docs/user_guide/dsintro.html#series) "
   ]
  }
 ],
 "metadata": {},
 "nbformat": 4,
 "nbformat_minor": 5
}
