{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "1a344451",
   "metadata": {},
   "source": [
    "# 4. Pandas DataFrame 생성과 기초 조작\n",
    "\n",
    "## 📚 학습 목표\n",
    "- Pandas DataFrame의 기본 개념과 구조 이해\n",
    "- 다양한 방법으로 DataFrame 생성하기\n",
    "- DataFrame의 기본 조작과 속성 활용\n",
    "- 컬럼과 행의 추가, 삭제, 수정 방법 습득\n",
    "\n",
    "## 🔍 문제 설명\n",
    "\n",
    "Pandas DataFrame은 2차원 라벨링된 데이터 구조로, 행과 열로 구성된 테이블 형태의 데이터를 효율적으로 다룰 수 있게 해줍니다. 데이터 분석의 핵심 도구이며, 실제 비즈니스 데이터를 다룰 때 가장 많이 사용됩니다.\n",
    "\n",
    "### 실전 활용 사례\n",
    "- **비즈니스 데이터**: 고객 정보, 판매 데이터, 재무 데이터\n",
    "- **과학 데이터**: 실험 결과, 측정 데이터, 연구 데이터\n",
    "- **웹 스크래핑**: 웹사이트에서 수집한 테이블 데이터\n",
    "- **데이터베이스 연동**: SQL 쿼리 결과를 DataFrame으로 변환\n",
    "\n",
    "## 📝 문제\n",
    "\n",
    "### 문제 4-1: DataFrame 생성\n",
    "1. 딕셔너리를 사용하여 직원 정보 DataFrame을 생성하세요.\n",
    "2. 리스트의 리스트를 사용하여 DataFrame을 생성하세요.\n",
    "3. NumPy 배열을 사용하여 DataFrame을 생성하세요.\n",
    "\n",
    "### 문제 4-2: DataFrame 기본 조작\n",
    "4. DataFrame의 기본 정보(shape, columns, index)를 확인하세요.\n",
    "5. 특정 컬럼을 선택하고 새로운 DataFrame을 만드세요.\n",
    "6. 특정 행을 선택하세요.\n",
    "\n",
    "### 문제 4-3: DataFrame 수정\n",
    "7. 새로운 컬럼을 추가하세요.\n",
    "8. 기존 컬럼의 값을 수정하세요.\n",
    "9. 특정 행을 삭제하세요.\n",
    "\n",
    "## 💡 해답 및 설명\n",
    "\n",
    "### 해답 4-1: DataFrame 생성\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9f4a8898",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "\n",
    "# 1. 딕셔너리를 사용하여 직원 정보 DataFrame 생성\n",
    "employee_data = {\n",
    "    '이름': ['김철수', '이영희', '박민수', '정수진', '최재영'],\n",
    "    '나이': [28, 35, 42, 31, 27],\n",
    "    '부서': ['개발', '인사', '개발', '마케팅', '개발'],\n",
    "    '급여': [3500000, 4200000, 3800000, 3900000, 3600000],\n",
    "    '입사일': ['2020-03-15', '2018-07-01', '2015-11-20', '2019-05-10', '2021-01-08']\n",
    "}\n",
    "\n",
    "df_employees = pd.DataFrame(employee_data)\n",
    "print(\"직원 정보 DataFrame:\")\n",
    "print(df_employees)\n",
    "print(f\"\\nDataFrame 형태: {df_employees.shape}\")\n",
    "print(f\"컬럼명: {list(df_employees.columns)}\")\n",
    "\n",
    "# 2. 리스트의 리스트를 사용하여 DataFrame 생성\n",
    "data_list = [\n",
    "    ['노트북', 1200000, 50, '전자제품'],\n",
    "    ['스마트폰', 800000, 100, '전자제품'],\n",
    "    ['태블릿', 500000, 30, '전자제품'],\n",
    "    ['이어폰', 150000, 200, '액세서리'],\n",
    "    ['스마트워치', 300000, 80, '액세서리']\n",
    "]\n",
    "\n",
    "df_products = pd.DataFrame(data_list, \n",
    "                          columns=['제품명', '가격', '재고', '카테고리'])\n",
    "print(\"\\n제품 정보 DataFrame:\")\n",
    "print(df_products)\n",
    "\n",
    "# 3. NumPy 배열을 사용하여 DataFrame 생성\n",
    "np.random.seed(42)\n",
    "random_data = np.random.randn(5, 4)  # 5행 4열의 랜덤 데이터\n",
    "df_random = pd.DataFrame(random_data, \n",
    "                        columns=['A', 'B', 'C', 'D'],\n",
    "                        index=['row1', 'row2', 'row3', 'row4', 'row5'])\n",
    "print(\"\\n랜덤 데이터 DataFrame:\")\n",
    "print(df_random)\n",
    "\n",
    "# 추가 생성 방법들\n",
    "print(\"\\n다양한 DataFrame 생성 방법:\")\n",
    "\n",
    "# Series의 딕셔너리로 생성\n",
    "series_dict = {\n",
    "    '수학': pd.Series([85, 92, 78, 96, 88], index=['학생1', '학생2', '학생3', '학생4', '학생5']),\n",
    "    '영어': pd.Series([90, 85, 92, 88, 95], index=['학생1', '학생2', '학생3', '학생4', '학생5']),\n",
    "    '과학': pd.Series([88, 90, 85, 92, 87], index=['학생1', '학생2', '학생3', '학생4', '학생5'])\n",
    "}\n",
    "\n",
    "df_scores = pd.DataFrame(series_dict)\n",
    "print(\"성적 DataFrame:\")\n",
    "print(df_scores)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3535b086",
   "metadata": {},
   "source": [
    "\n",
    "\n",
    "### 해답 4-2: DataFrame 기본 조작\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0326e955",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 4. DataFrame의 기본 정보 확인\n",
    "print(\"DataFrame 기본 정보:\")\n",
    "print(f\"형태 (행, 열): {df_employees.shape}\")\n",
    "print(f\"컬럼명: {list(df_employees.columns)}\")\n",
    "print(f\"인덱스: {list(df_employees.index)}\")\n",
    "print(f\"데이터 타입:\\n{df_employees.dtypes}\")\n",
    "print(f\"메모리 사용량: {df_employees.memory_usage(deep=True).sum()} bytes\")\n",
    "\n",
    "# info() 메서드로 한 번에 확인\n",
    "print(\"\\nDataFrame 상세 정보:\")\n",
    "print(df_employees.info())\n",
    "\n",
    "# describe() 메서드로 수치형 데이터 요약\n",
    "print(\"\\n수치형 데이터 통계:\")\n",
    "print(df_employees.describe())\n",
    "\n",
    "# 5. 특정 컬럼 선택\n",
    "print(\"\\n컬럼 선택:\")\n",
    "# 단일 컬럼 선택 (Series 반환)\n",
    "names = df_employees['이름']\n",
    "print(\"이름 컬럼 (Series):\")\n",
    "print(names)\n",
    "\n",
    "# 여러 컬럼 선택 (DataFrame 반환)\n",
    "basic_info = df_employees[['이름', '나이', '부서']]\n",
    "print(\"\\n기본 정보 (DataFrame):\")\n",
    "print(basic_info)\n",
    "\n",
    "# 6. 특정 행 선택\n",
    "print(\"\\n행 선택:\")\n",
    "# 인덱스로 선택\n",
    "first_row = df_employees.iloc[0]\n",
    "print(\"첫 번째 행:\")\n",
    "print(first_row)\n",
    "\n",
    "# 라벨로 선택\n",
    "second_row = df_employees.loc[1]\n",
    "print(\"\\n두 번째 행:\")\n",
    "print(second_row)\n",
    "\n",
    "# 여러 행 선택\n",
    "first_three_rows = df_employees.iloc[0:3]\n",
    "print(\"\\n처음 3행:\")\n",
    "print(first_three_rows)\n",
    "\n",
    "# 조건부 행 선택\n",
    "dev_employees = df_employees[df_employees['부서'] == '개발']\n",
    "print(\"\\n개발부 직원:\")\n",
    "print(dev_employees)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "783c6780",
   "metadata": {},
   "source": [
    "\n",
    "\n",
    "### 해답 4-3: DataFrame 수정\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8aa1a476",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 7. 새로운 컬럼 추가\n",
    "print(\"새로운 컬럼 추가:\")\n",
    "\n",
    "# 스칼라 값으로 컬럼 추가\n",
    "df_employees['성별'] = '남성'\n",
    "print(\"성별 컬럼 추가 후:\")\n",
    "print(df_employees)\n",
    "\n",
    "# 계산된 값으로 컬럼 추가\n",
    "df_employees['연봉'] = df_employees['급여'] * 12\n",
    "print(\"\\n연봉 컬럼 추가 후:\")\n",
    "print(df_employees)\n",
    "\n",
    "# 조건부 값으로 컬럼 추가\n",
    "df_employees['경력'] = df_employees['나이'] - 22\n",
    "print(\"\\n경력 컬럼 추가 후:\")\n",
    "print(df_employees)\n",
    "\n",
    "# 8. 기존 컬럼 값 수정\n",
    "print(\"\\n컬럼 값 수정:\")\n",
    "\n",
    "# 특정 조건으로 값 수정\n",
    "df_employees.loc[df_employees['부서'] == '개발', '성별'] = '남성'\n",
    "df_employees.loc[df_employees['부서'] == '인사', '성별'] = '여성'\n",
    "df_employees.loc[df_employees['부서'] == '마케팅', '성별'] = '여성'\n",
    "\n",
    "print(\"성별 수정 후:\")\n",
    "print(df_employees)\n",
    "\n",
    "# 스칼라 연산으로 값 수정\n",
    "df_employees['급여'] = df_employees['급여'] * 1.1  # 10% 인상\n",
    "print(\"\\n급여 10% 인상 후:\")\n",
    "print(df_employees)\n",
    "\n",
    "# 9. 특정 행 삭제\n",
    "print(\"\\n행 삭제:\")\n",
    "\n",
    "# 인덱스로 행 삭제\n",
    "df_employees_dropped = df_employees.drop(2)  # 인덱스 2인 행 삭제\n",
    "print(\"인덱스 2 행 삭제 후:\")\n",
    "print(df_employees_dropped)\n",
    "\n",
    "# 조건부로 행 삭제\n",
    "df_employees_filtered = df_employees[df_employees['나이'] < 40]\n",
    "print(\"\\n40세 미만 직원만:\")\n",
    "print(df_employees_filtered)\n",
    "\n",
    "# 컬럼 삭제\n",
    "df_employees_clean = df_employees.drop(['성별', '경력'], axis=1)\n",
    "print(\"\\n성별, 경력 컬럼 삭제 후:\")\n",
    "print(df_employees_clean)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f99c0122",
   "metadata": {},
   "source": [
    "\n",
    "\n",
    "## 🔧 주요 DataFrame 메서드와 속성\n",
    "\n",
    "### 기본 속성\n",
    "- `df.shape`: (행 수, 열 수) 튜플\n",
    "- `df.columns`: 컬럼명 인덱스\n",
    "- `df.index`: 행 인덱스\n",
    "- `df.dtypes`: 각 컬럼의 데이터 타입\n",
    "- `df.values`: NumPy 배열로 변환\n",
    "- `df.size`: 전체 원소 개수\n",
    "\n",
    "### 정보 확인 메서드\n",
    "- `df.info()`: DataFrame 정보 요약\n",
    "- `df.describe()`: 수치형 데이터 통계\n",
    "- `df.head(n)`: 처음 n행\n",
    "- `df.tail(n)`: 마지막 n행\n",
    "- `df.isnull()`: NaN 값 확인\n",
    "- `df.notnull()`: 비NaN 값 확인\n",
    "\n",
    "### 선택 메서드\n",
    "- `df.loc[]`: 라벨 기반 인덱싱\n",
    "- `df.iloc[]`: 정수 위치 기반 인덱싱\n",
    "- `df.at[]`: 단일 라벨 값\n",
    "- `df.iat[]`: 단일 위치 값\n",
    "\n",
    "### 수정 메서드\n",
    "- `df.drop()`: 행/열 삭제\n",
    "- `df.rename()`: 컬럼명/인덱스명 변경\n",
    "- `df.set_index()`: 인덱스 설정\n",
    "- `df.reset_index()`: 인덱스 초기화\n",
    "- `df.sort_values()`: 값 기준 정렬\n",
    "- `df.sort_index()`: 인덱스 기준 정렬\n",
    "\n",
    "## 📊 추가 연습문제\n",
    "\n",
    "### 연습문제 1: DataFrame 생성과 조작\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "45620a35",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 다음 문제들을 풀어보세요:\n",
    "# 1. 학생들의 성적 데이터를 DataFrame으로 생성하세요.\n",
    "#    (이름, 수학, 영어, 과학, 사회)\n",
    "# 2. 각 학생의 평균 점수를 계산하여 새로운 컬럼을 추가하세요.\n",
    "# 3. 평균 점수가 85점 이상인 학생들만 선택하세요."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8c875d25",
   "metadata": {},
   "source": [
    "\n",
    "\n",
    "### 연습문제 2: 데이터 필터링과 정렬\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "764363d0",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 다음 DataFrame을 생성하고 문제를 풀어보세요:\n",
    "sales_data = pd.DataFrame({\n",
    "    '제품명': ['노트북', '스마트폰', '태블릿', '이어폰', '스마트워치'],\n",
    "    '가격': [1200000, 800000, 500000, 150000, 300000],\n",
    "    '판매량': [50, 100, 30, 200, 80],\n",
    "    '카테고리': ['전자제품', '전자제품', '전자제품', '액세서리', '액세서리']\n",
    "})\n",
    "\n",
    "# 1. 가격이 500,000원 이상인 제품만 선택하세요.\n",
    "# 2. 판매량 기준으로 내림차순 정렬하세요.\n",
    "# 3. 각 제품의 총 매출액(가격 × 판매량)을 계산하세요."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1b9b54f0",
   "metadata": {},
   "source": [
    "\n",
    "\n",
    "### 연습문제 3: 조건부 데이터 처리\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "19e820b5",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 다음 DataFrame을 생성하고 문제를 풀어보세요:\n",
    "customer_data = pd.DataFrame({\n",
    "    '고객ID': [1, 2, 3, 4, 5, 6, 7, 8],\n",
    "    '이름': ['김철수', '이영희', '박민수', '정수진', '최재영', '강지원', '윤미라', '손태식'],\n",
    "    '나이': [28, 35, 42, 31, 27, 36, 29, 45],\n",
    "    '등급': ['Gold', 'Silver', 'Gold', 'Platinum', 'Silver', 'Gold', 'Silver', 'Platinum'],\n",
    "    '구매금액': [150000, 80000, 200000, 300000, 120000, 180000, 90000, 250000]\n",
    "})\n",
    "\n",
    "# 1. 나이가 30세 이상인 고객만 선택하세요.\n",
    "# 2. Gold 등급 고객들의 평균 구매금액을 계산하세요.\n",
    "# 3. 등급별 고객 수를 계산하세요."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cf57428e",
   "metadata": {},
   "source": [
    "\n",
    "\n",
    "## ⚠️ 주의사항 및 팁\n",
    "\n",
    "1. **인덱싱 방법**: `loc`는 라벨 기반, `iloc`는 정수 위치 기반입니다.\n",
    "2. **뷰 vs 복사**: 슬라이싱은 뷰를 반환하지만, 조건부 선택은 복사를 반환합니다.\n",
    "3. **데이터 타입**: DataFrame은 각 컬럼마다 다른 데이터 타입을 가질 수 있습니다.\n",
    "4. **메모리 효율성**: 큰 데이터셋에서는 적절한 데이터 타입을 선택하는 것이 중요합니다.\n",
    "5. **인덱스 관리**: 인덱스는 고유해야 하며, 중복된 인덱스가 있으면 경고가 발생합니다.\n",
    "\n",
    "## 🎯 실전 활용 예제\n",
    "\n",
    "### 예제 1: 고객 데이터 분석\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ce8a0ab4",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 고객 데이터 생성\n",
    "np.random.seed(42)\n",
    "n_customers = 100\n",
    "\n",
    "customer_data = pd.DataFrame({\n",
    "    '고객ID': range(1, n_customers + 1),\n",
    "    '나이': np.random.randint(18, 70, n_customers),\n",
    "    '성별': np.random.choice(['남성', '여성'], n_customers),\n",
    "    '등급': np.random.choice(['Bronze', 'Silver', 'Gold', 'Platinum'], n_customers, p=[0.4, 0.3, 0.2, 0.1]),\n",
    "    '연간구매액': np.random.normal(500000, 200000, n_customers),\n",
    "    '가입일': pd.date_range('2020-01-01', periods=n_customers, freq='D')\n",
    "})\n",
    "\n",
    "print(\"고객 데이터 기본 정보:\")\n",
    "print(customer_data.info())\n",
    "\n",
    "# 등급별 통계\n",
    "grade_stats = customer_data.groupby('등급').agg({\n",
    "    '나이': ['mean', 'std'],\n",
    "    '연간구매액': ['mean', 'sum', 'count']\n",
    "}).round(2)\n",
    "\n",
    "print(\"\\n등급별 통계:\")\n",
    "print(grade_stats)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b8cb4871",
   "metadata": {},
   "source": [
    "\n",
    "\n",
    "### 예제 2: 판매 데이터 분석\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "05aebcf4",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 월별 판매 데이터 생성\n",
    "np.random.seed(42)\n",
    "months = pd.date_range('2023-01-01', periods=12, freq='M')\n",
    "products = ['노트북', '스마트폰', '태블릿', '이어폰', '스마트워치']\n",
    "\n",
    "sales_data = []\n",
    "for month in months:\n",
    "    for product in products:\n",
    "        sales_data.append({\n",
    "            '월': month,\n",
    "            '제품': product,\n",
    "            '판매량': np.random.randint(10, 100),\n",
    "            '단가': np.random.choice([100000, 150000, 200000, 50000, 80000])\n",
    "        })\n",
    "\n",
    "df_sales = pd.DataFrame(sales_data)\n",
    "df_sales['매출액'] = df_sales['판매량'] * df_sales['단가']\n",
    "\n",
    "print(\"판매 데이터:\")\n",
    "print(df_sales.head(10))\n",
    "\n",
    "# 월별 총 매출액\n",
    "monthly_sales = df_sales.groupby('월')['매출액'].sum()\n",
    "print(\"\\n월별 총 매출액:\")\n",
    "print(monthly_sales)\n",
    "\n",
    "# 제품별 평균 판매량\n",
    "product_avg = df_sales.groupby('제품')['판매량'].mean()\n",
    "print(\"\\n제품별 평균 판매량:\")\n",
    "print(product_avg)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b386e41b",
   "metadata": {},
   "source": [
    "\n",
    "\n",
    "### 예제 3: 주식 데이터 분석\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "40d84ca6",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 주식 가격 데이터 생성\n",
    "np.random.seed(42)\n",
    "dates = pd.date_range('2023-01-01', periods=100, freq='D')\n",
    "stocks = ['삼성전자', 'SK하이닉스', 'LG에너지솔루션', '현대차', '기아']\n",
    "\n",
    "stock_data = []\n",
    "for date in dates:\n",
    "    for stock in stocks:\n",
    "        stock_data.append({\n",
    "            '날짜': date,\n",
    "            '종목': stock,\n",
    "            '시가': np.random.normal(50000, 10000),\n",
    "            '고가': np.random.normal(52000, 10000),\n",
    "            '저가': np.random.normal(48000, 10000),\n",
    "            '종가': np.random.normal(50000, 10000),\n",
    "            '거래량': np.random.randint(1000000, 10000000)\n",
    "        })\n",
    "\n",
    "df_stocks = pd.DataFrame(stock_data)\n",
    "\n",
    "# 일별 수익률 계산\n",
    "df_stocks['수익률'] = df_stocks.groupby('종목')['종가'].pct_change()\n",
    "\n",
    "print(\"주식 데이터:\")\n",
    "print(df_stocks.head(10))\n",
    "\n",
    "# 종목별 평균 수익률\n",
    "stock_returns = df_stocks.groupby('종목')['수익률'].agg(['mean', 'std']).round(4)\n",
    "print(\"\\n종목별 수익률 통계:\")\n",
    "print(stock_returns)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2f480e29",
   "metadata": {},
   "source": [
    "\n",
    "\n",
    "## 📚 다음 단계\n",
    "\n",
    "이제 Pandas DataFrame의 기본을 익혔습니다. 다음 단계에서는:\n",
    "- 데이터 인덱싱, 슬라이싱, 필터링\n",
    "- 결측치 처리와 데이터 정제\n",
    "- 그룹화와 집계\n",
    "- 데이터 병합과 조인\n",
    "\n",
    "을 학습하게 됩니다.\n",
    "\n",
    "---\n",
    "\n",
    "**참고 자료:**\n",
    "- [Pandas DataFrame 공식 문서](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.html)\n",
    "- [Pandas DataFrame 튜토리얼](https://pandas.pydata.org/docs/user_guide/dsintro.html#dataframe) "
   ]
  }
 ],
 "metadata": {},
 "nbformat": 4,
 "nbformat_minor": 5
}
