{"id":4219,"date":"2026-03-01T10:13:13","date_gmt":"2026-03-01T02:13:13","guid":{"rendered":"http:\/\/viplao.com\/?p=4219"},"modified":"2026-03-01T10:13:15","modified_gmt":"2026-03-01T02:13:15","slug":"%e6%95%b0%e6%8d%ae%e6%8a%80%e8%83%bd%ef%bc%88skills%ef%bc%89-%ef%bc%9aday-4%ef%bc%9a%e6%95%b0%e6%8d%ae%e9%87%87%e9%9b%86%e4%b8%8e%e6%b8%85%e6%b4%97%e8%87%aa%e5%8a%a8%e5%8c%96","status":"publish","type":"post","link":"http:\/\/viplao.com\/index.php\/2026\/03\/01\/%e6%95%b0%e6%8d%ae%e6%8a%80%e8%83%bd%ef%bc%88skills%ef%bc%89-%ef%bc%9aday-4%ef%bc%9a%e6%95%b0%e6%8d%ae%e9%87%87%e9%9b%86%e4%b8%8e%e6%b8%85%e6%b4%97%e8%87%aa%e5%8a%a8%e5%8c%96\/","title":{"rendered":"\u6570\u636e\u6280\u80fd\uff08SKILLS\uff09 \uff1aDay 4\uff1a\u6570\u636e\u91c7\u96c6\u4e0e\u6e05\u6d17\u81ea\u52a8\u5316"},"content":{"rendered":"\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_71 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">\u6587\u7ae0\u76ee\u5f55<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 eztoc-toggle-hide-by-default' ><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"http:\/\/viplao.com\/index.php\/2026\/03\/01\/%e6%95%b0%e6%8d%ae%e6%8a%80%e8%83%bd%ef%bc%88skills%ef%bc%89-%ef%bc%9aday-4%ef%bc%9a%e6%95%b0%e6%8d%ae%e9%87%87%e9%9b%86%e4%b8%8e%e6%b8%85%e6%b4%97%e8%87%aa%e5%8a%a8%e5%8c%96\/#%E8%AF%BE%E7%A8%8B%E7%9B%AE%E6%A0%87\" title=\"\u8bfe\u7a0b\u76ee\u6807\">\u8bfe\u7a0b\u76ee\u6807<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"http:\/\/viplao.com\/index.php\/2026\/03\/01\/%e6%95%b0%e6%8d%ae%e6%8a%80%e8%83%bd%ef%bc%88skills%ef%bc%89-%ef%bc%9aday-4%ef%bc%9a%e6%95%b0%e6%8d%ae%e9%87%87%e9%9b%86%e4%b8%8e%e6%b8%85%e6%b4%97%e8%87%aa%e5%8a%a8%e5%8c%96\/#%E6%A0%B8%E5%BF%83%E6%8A%80%E8%83%BD\" title=\"\u6838\u5fc3\u6280\u80fd\">\u6838\u5fc3\u6280\u80fd<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"http:\/\/viplao.com\/index.php\/2026\/03\/01\/%e6%95%b0%e6%8d%ae%e6%8a%80%e8%83%bd%ef%bc%88skills%ef%bc%89-%ef%bc%9aday-4%ef%bc%9a%e6%95%b0%e6%8d%ae%e9%87%87%e9%9b%86%e4%b8%8e%e6%b8%85%e6%b4%97%e8%87%aa%e5%8a%a8%e5%8c%96\/#%E8%AF%BE%E4%BB%B6%E5%86%85%E5%AE%B9\" title=\"\u8bfe\u4ef6\u5185\u5bb9\">\u8bfe\u4ef6\u5185\u5bb9<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"http:\/\/viplao.com\/index.php\/2026\/03\/01\/%e6%95%b0%e6%8d%ae%e6%8a%80%e8%83%bd%ef%bc%88skills%ef%bc%89-%ef%bc%9aday-4%ef%bc%9a%e6%95%b0%e6%8d%ae%e9%87%87%e9%9b%86%e4%b8%8e%e6%b8%85%e6%b4%97%e8%87%aa%e5%8a%a8%e5%8c%96\/#1_%E6%95%B0%E6%8D%AE%E9%87%87%E9%9B%86%E6%A8%A1%E5%9D%97\" title=\"1. \u6570\u636e\u91c7\u96c6\u6a21\u5757\">1. \u6570\u636e\u91c7\u96c6\u6a21\u5757<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"http:\/\/viplao.com\/index.php\/2026\/03\/01\/%e6%95%b0%e6%8d%ae%e6%8a%80%e8%83%bd%ef%bc%88skills%ef%bc%89-%ef%bc%9aday-4%ef%bc%9a%e6%95%b0%e6%8d%ae%e9%87%87%e9%9b%86%e4%b8%8e%e6%b8%85%e6%b4%97%e8%87%aa%e5%8a%a8%e5%8c%96\/#2_%E6%95%B0%E6%8D%AE%E6%B8%85%E6%B4%97%E6%A8%A1%E5%9D%97\" title=\"2. \u6570\u636e\u6e05\u6d17\u6a21\u5757\">2. \u6570\u636e\u6e05\u6d17\u6a21\u5757<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"http:\/\/viplao.com\/index.php\/2026\/03\/01\/%e6%95%b0%e6%8d%ae%e6%8a%80%e8%83%bd%ef%bc%88skills%ef%bc%89-%ef%bc%9aday-4%ef%bc%9a%e6%95%b0%e6%8d%ae%e9%87%87%e9%9b%86%e4%b8%8e%e6%b8%85%e6%b4%97%e8%87%aa%e5%8a%a8%e5%8c%96\/#%E5%AE%89%E8%A3%85%E8%A6%81%E6%B1%82\" title=\"\u5b89\u88c5\u8981\u6c42\">\u5b89\u88c5\u8981\u6c42<\/a><\/li><\/ul><\/nav><\/div>\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"%E8%AF%BE%E7%A8%8B%E7%9B%AE%E6%A0%87\"><\/span><strong>\u8bfe\u7a0b\u76ee\u6807<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>\u638c\u63e1\u4ece\u591a\u6e90\uff08Excel\u3001\u6570\u636e\u5e93\u3001API\uff09\u81ea\u52a8\u5316\u91c7\u96c6\u7535\u5546\u6570\u636e\uff0c\u5e76\u8fdb\u884c\u6807\u51c6\u5316\u6e05\u6d17\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"%E6%A0%B8%E5%BF%83%E6%8A%80%E8%83%BD\"><\/span><strong>\u6838\u5fc3\u6280\u80fd<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<ul>\n<li>\u591a\u6e90\u6570\u636e\u81ea\u52a8\u91c7\u96c6<\/li>\n\n\n\n<li>\u7f3a\u5931\u503c\u3001\u5f02\u5e38\u503c\u3001\u91cd\u590d\u503c\u81ea\u52a8\u5316\u5904\u7406<\/li>\n\n\n\n<li>\u6570\u636e\u6807\u51c6\u5316\u4e0e\u7c7b\u578b\u8f6c\u6362<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"%E8%AF%BE%E4%BB%B6%E5%86%85%E5%AE%B9\"><\/span><strong>\u8bfe\u4ef6\u5185\u5bb9<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"1_%E6%95%B0%E6%8D%AE%E9%87%87%E9%9B%86%E6%A8%A1%E5%9D%97\"><\/span><strong>1. \u6570\u636e\u91c7\u96c6\u6a21\u5757<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code># \u5b89\u88c5\u4f9d\u8d56\uff1apip install pandas numpy sqlalchemy pymysql openpyxl xlrd\nimport pandas as pd\nimport numpy as np\nfrom sqlalchemy import create_engine\nimport os\n\nclass DataCollector:\n    def __init__(self):\n        self.data_sources = {}\n    \n    def from_excel(self, file_path, sheet_name=0):\n        \"\"\"\u4eceExcel\u6587\u4ef6\u8bfb\u53d6\u6570\u636e\"\"\"\n        try:\n            df = pd.read_excel(file_path, sheet_name=sheet_name)\n            print(f\"\u2705 Excel\u6570\u636e\u52a0\u8f7d\u6210\u529f: {file_path}, \u5f62\u72b6: {df.shape}\")\n            return df\n        except Exception as e:\n            print(f\"\u274c Excel\u52a0\u8f7d\u5931\u8d25: {e}\")\n            return None\n    \n    def from_csv(self, file_path, encoding='utf-8'):\n        \"\"\"\u4eceCSV\u6587\u4ef6\u8bfb\u53d6\u6570\u636e\"\"\"\n        try:\n            df = pd.read_csv(file_path, encoding=encoding)\n            print(f\"\u2705 CSV\u6570\u636e\u52a0\u8f7d\u6210\u529f: {file_path}, \u5f62\u72b6: {df.shape}\")\n            return df\n        except Exception as e:\n            print(f\"\u274c CSV\u52a0\u8f7d\u5931\u8d25: {e}\")\n            return None\n    \n    def from_mysql(self, host, user, password, database, query):\n        \"\"\"\u4eceMySQL\u6570\u636e\u5e93\u8bfb\u53d6\u6570\u636e\"\"\"\n        try:\n            engine = create_engine(f'mysql+pymysql:\/\/{user}:{password}@{host}\/{database}')\n            df = pd.read_sql(query, engine)\n            print(f\"\u2705 MySQL\u6570\u636e\u52a0\u8f7d\u6210\u529f, \u5f62\u72b6: {df.shape}\")\n            return df\n        except Exception as e:\n            print(f\"\u274c MySQL\u8fde\u63a5\u5931\u8d25: {e}\")\n            return None\n    \n    def merge_multiple_sources(self, data_dict):\n        \"\"\"\u5408\u5e76\u591a\u4e2a\u6570\u636e\u6e90\"\"\"\n        merged_data = pd.DataFrame()\n        for name, df in data_dict.items():\n            if merged_data.empty:\n                merged_data = df\n            else:\n                merged_data = pd.merge(merged_data, df, how='outer')\n        return merged_data\n\n# \u6848\u4f8b\u6570\u636e\u811a\u672c\ndef create_sample_data():\n    \"\"\"\u751f\u6210\u793a\u4f8b\u7535\u5546\u6570\u636e\"\"\"\n    np.random.seed(42)\n    \n    # \u7528\u6237\u6570\u636e\n    user_data = pd.DataFrame({\n        'user_id': range(1001, 1021),\n        'user_name': &#91;f'user_{i}' for i in range(1001, 1021)],\n        'registration_date': pd.date_range('2024-01-01', periods=20),\n        'user_level': np.random.choice(&#91;'\u9752\u94dc', '\u767d\u94f6', '\u9ec4\u91d1', '\u94c2\u91d1', '\u94bb\u77f3'], 20),\n        'total_spent': np.random.uniform(100, 10000, 20).round(2),\n        'city': np.random.choice(&#91;'\u5317\u4eac', '\u4e0a\u6d77', '\u5e7f\u5dde', '\u6df1\u5733', '\u676d\u5dde'], 20)\n    })\n    \n    # \u8ba2\u5355\u6570\u636e\n    order_data = pd.DataFrame({\n        'order_id': range(5001, 5021),\n        'user_id': np.random.choice(range(1001, 1021), 20),\n        'order_date': pd.date_range('2024-03-01', periods=20),\n        'product_id': np.random.choice(&#91;'P001', 'P002', 'P003', 'P004', 'P005'], 20),\n        'quantity': np.random.randint(1, 10, 20),\n        'unit_price': np.random.uniform(50, 500, 20).round(2),\n        'payment_method': np.random.choice(&#91;'\u652f\u4ed8\u5b9d', '\u5fae\u4fe1', '\u94f6\u884c\u5361', '\u4fe1\u7528\u5361'], 20),\n        'order_status': np.random.choice(&#91;'\u5df2\u5b8c\u6210', '\u5df2\u53d1\u8d27', '\u5f85\u4ed8\u6b3e', '\u5df2\u53d6\u6d88'], 20)\n    })\n    \n    # \u5546\u54c1\u6570\u636e\n    product_data = pd.DataFrame({\n        'product_id': &#91;'P001', 'P002', 'P003', 'P004', 'P005'],\n        'product_name': &#91;'\u667a\u80fd\u624b\u673a', '\u7b14\u8bb0\u672c\u7535\u8111', '\u65e0\u7ebf\u8033\u673a', '\u667a\u80fd\u624b\u8868', '\u5e73\u677f\u7535\u8111'],\n        'category': &#91;'\u7535\u5b50\u4ea7\u54c1', '\u7535\u5b50\u4ea7\u54c1', '\u914d\u4ef6', '\u7535\u5b50\u4ea7\u54c1', '\u7535\u5b50\u4ea7\u54c1'],\n        'brand': &#91;'\u54c1\u724cA', '\u54c1\u724cB', '\u54c1\u724cC', '\u54c1\u724cD', '\u54c1\u724cE'],\n        'cost_price': &#91;1999, 5999, 299, 1299, 2999],\n        'market_price': &#91;2499, 6999, 399, 1599, 3499]\n    })\n    \n    # \u4fdd\u5b58\u793a\u4f8b\u6570\u636e\n    user_data.to_csv('sample_user_data.csv', index=False, encoding='utf-8')\n    order_data.to_csv('sample_order_data.csv', index=False, encoding='utf-8')\n    product_data.to_csv('sample_product_data.csv', index=False, encoding='utf-8')\n    \n    print(\"\u2705 \u793a\u4f8b\u6570\u636e\u5df2\u751f\u6210:\")\n    print(f\"  \u7528\u6237\u6570\u636e: {user_data.shape}\")\n    print(f\"  \u8ba2\u5355\u6570\u636e: {order_data.shape}\")\n    print(f\"  \u5546\u54c1\u6570\u636e: {product_data.shape}\")\n    \n    return user_data, order_data, product_data\n\n# \u8fd0\u884c\u793a\u4f8b\nif __name__ == \"__main__\":\n    # 1. \u751f\u6210\u793a\u4f8b\u6570\u636e\n    print(\"=\"*50)\n    print(\"\u6b65\u9aa41: \u751f\u6210\u793a\u4f8b\u7535\u5546\u6570\u636e\")\n    print(\"=\"*50)\n    user_df, order_df, product_df = create_sample_data()\n    \n    # 2. \u6570\u636e\u91c7\u96c6\u6f14\u793a\n    print(\"\\n\" + \"=\"*50)\n    print(\"\u6b65\u9aa42: \u591a\u6e90\u6570\u636e\u91c7\u96c6\u6f14\u793a\")\n    print(\"=\"*50)\n    \n    collector = DataCollector()\n    \n    # \u4eceCSV\u91c7\u96c6\n    user_data = collector.from_csv('sample_user_data.csv')\n    order_data = collector.from_csv('sample_order_data.csv')\n    product_data = collector.from_csv('sample_product_data.csv')\n    \n    # \u663e\u793a\u6570\u636e\u9884\u89c8\n    print(\"\\n\u7528\u6237\u6570\u636e\u9884\u89c8:\")\n    print(user_data.head())\n    \n    print(\"\\n\u8ba2\u5355\u6570\u636e\u9884\u89c8:\")\n    print(order_data.head())\n    \n    print(\"\\n\u5546\u54c1\u6570\u636e\u9884\u89c8:\")\n    print(product_data.head())\n<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"2_%E6%95%B0%E6%8D%AE%E6%B8%85%E6%B4%97%E6%A8%A1%E5%9D%97\"><\/span><strong>2. \u6570\u636e\u6e05\u6d17\u6a21\u5757<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code>class DataCleaner:\n    def __init__(self):\n        self.cleaning_report = {}\n    \n    def detect_missing_values(self, df):\n        \"\"\"\u68c0\u6d4b\u7f3a\u5931\u503c\"\"\"\n        missing_info = df.isnull().sum()\n        missing_percent = (missing_info \/ len(df) * 100).round(2)\n        \n        missing_df = pd.DataFrame({\n            '\u7f3a\u5931\u6570\u91cf': missing_info,\n            '\u7f3a\u5931\u6bd4\u4f8b%': missing_percent\n        })\n        \n        self.cleaning_report&#91;'missing_values'] = missing_df&#91;missing_df&#91;'\u7f3a\u5931\u6570\u91cf'] &gt; 0]\n        return self.cleaning_report&#91;'missing_values']\n    \n    def handle_missing_values(self, df, strategy='mean', columns=None):\n        \"\"\"\u5904\u7406\u7f3a\u5931\u503c\"\"\"\n        df_clean = df.copy()\n        \n        if columns is None:\n            columns = df.columns\n        \n        for col in columns:\n            if df&#91;col].isnull().sum() &gt; 0:\n                if strategy == 'mean' and pd.api.types.is_numeric_dtype(df&#91;col]):\n                    df_clean&#91;col] = df&#91;col].fillna(df&#91;col].mean())\n                elif strategy == 'median' and pd.api.types.is_numeric_dtype(df&#91;col]):\n                    df_clean&#91;col] = df&#91;col].fillna(df&#91;col].median())\n                elif strategy == 'mode':\n                    df_clean&#91;col] = df&#91;col].fillna(df&#91;col].mode()&#91;0](@ref)\n                elif strategy == 'drop':\n                    df_clean = df_clean.dropna(subset=&#91;col])\n                elif strategy == 'ffill':\n                    df_clean&#91;col] = df&#91;col].fillna(method='ffill')\n                elif strategy == 'bfill':\n                    df_clean&#91;col] = df&#91;col].fillna(method='bfill')\n                else:\n                    df_clean&#91;col] = df&#91;col].fillna('\u672a\u77e5')\n        \n        print(f\"\u2705 \u7f3a\u5931\u503c\u5904\u7406\u5b8c\u6210 - \u7b56\u7565: {strategy}\")\n        return df_clean\n    \n    def detect_outliers(self, df, column, method='iqr'):\n        \"\"\"\u68c0\u6d4b\u5f02\u5e38\u503c\"\"\"\n        if not pd.api.types.is_numeric_dtype(df&#91;column]):\n            print(f\"\u26a0\ufe0f  {column} \u4e0d\u662f\u6570\u503c\u578b\uff0c\u8df3\u8fc7\u5f02\u5e38\u503c\u68c0\u6d4b\")\n            return None\n        \n        if method == 'iqr':\n            Q1 = df&#91;column].quantile(0.25)\n            Q3 = df&#91;column].quantile(0.75)\n            IQR = Q3 - Q1\n            lower_bound = Q1 - 1.5 * IQR\n            upper_bound = Q3 + 1.5 * IQR\n            \n            outliers = df&#91;(df&#91;column] &lt; lower_bound) | (df&#91;column] &gt; upper_bound)]\n            \n            outlier_info = {\n                '\u5217\u540d': column,\n                '\u5f02\u5e38\u503c\u6570\u91cf': len(outliers),\n                '\u5f02\u5e38\u503c\u6bd4\u4f8b%': (len(outliers) \/ len(df) * 100).round(2),\n                '\u4e0b\u9650': lower_bound,\n                '\u4e0a\u9650': upper_bound,\n                '\u6700\u5c0f\u503c': df&#91;column].min(),\n                '\u6700\u5927\u503c': df&#91;column].max()\n            }\n            \n            self.cleaning_report.setdefault('outliers', &#91;]).append(outlier_info)\n            return outliers\n        \n        return None\n    \n    def handle_outliers(self, df, column, method='cap'):\n        \"\"\"\u5904\u7406\u5f02\u5e38\u503c\"\"\"\n        if not pd.api.types.is_numeric_dtype(df&#91;column]):\n            return df\n        \n        df_clean = df.copy()\n        \n        if method == 'cap':\n            Q1 = df&#91;column].quantile(0.25)\n            Q3 = df&#91;column].quantile(0.75)\n            IQR = Q3 - Q1\n            lower_bound = Q1 - 1.5 * IQR\n            upper_bound = Q3 + 1.5 * IQR\n            \n            df_clean&#91;column] = df_clean&#91;column].clip(lower_bound, upper_bound)\n            print(f\"\u2705 \u5f02\u5e38\u503c\u5904\u7406\u5b8c\u6210 - {column}: \u5c01\u9876\u6cd5\")\n        \n        elif method == 'remove':\n            Q1 = df&#91;column].quantile(0.25)\n            Q3 = df&#91;column].quantile(0.75)\n            IQR = Q3 - Q1\n            lower_bound = Q1 - 1.5 * IQR\n            upper_bound = Q3 + 1.5 * IQR\n            \n            df_clean = df_clean&#91;(df_clean&#91;column] &gt;= lower_bound) &amp; \n                               (df_clean&#91;column] &lt;= upper_bound)]\n            print(f\"\u2705 \u5f02\u5e38\u503c\u5904\u7406\u5b8c\u6210 - {column}: \u5220\u9664\u6cd5\")\n        \n        return df_clean\n    \n    def detect_duplicates(self, df, subset=None):\n        \"\"\"\u68c0\u6d4b\u91cd\u590d\u503c\"\"\"\n        if subset is None:\n            duplicates = df&#91;df.duplicated()]\n        else:\n            duplicates = df&#91;df.duplicated(subset=subset)]\n        \n        self.cleaning_report&#91;'duplicates'] = {\n            '\u91cd\u590d\u884c\u6570': len(duplicates),\n            '\u91cd\u590d\u6bd4\u4f8b%': (len(duplicates) \/ len(df) * 100).round(2)\n        }\n        \n        return duplicates\n    \n    def remove_duplicates(self, df, subset=None, keep='first'):\n        \"\"\"\u5220\u9664\u91cd\u590d\u503c\"\"\"\n        df_clean = df.drop_duplicates(subset=subset, keep=keep)\n        removed = len(df) - len(df_clean)\n        print(f\"\u2705 \u5220\u9664 {removed} \u6761\u91cd\u590d\u8bb0\u5f55\")\n        return df_clean\n    \n    def standardize_data_types(self, df, column_type_map):\n        \"\"\"\u6807\u51c6\u5316\u6570\u636e\u7c7b\u578b\"\"\"\n        df_clean = df.copy()\n        \n        for col, dtype in column_type_map.items():\n            if col in df_clean.columns:\n                try:\n                    if dtype == 'datetime':\n                        df_clean&#91;col] = pd.to_datetime(df_clean&#91;col])\n                    elif dtype == 'numeric':\n                        df_clean&#91;col] = pd.to_numeric(df_clean&#91;col], errors='coerce')\n                    elif dtype == 'category':\n                        df_clean&#91;col] = df_clean&#91;col].astype('category')\n                    elif dtype == 'string':\n                        df_clean&#91;col] = df_clean&#91;col].astype(str)\n                    print(f\"  {col} -&gt; {dtype}\")\n                except Exception as e:\n                    print(f\"\u26a0\ufe0f  {col} \u7c7b\u578b\u8f6c\u6362\u5931\u8d25: {e}\")\n        \n        return df_clean\n    \n    def generate_cleaning_report(self):\n        \"\"\"\u751f\u6210\u6e05\u6d17\u62a5\u544a\"\"\"\n        print(\"\\n\" + \"=\"*50)\n        print(\"\u6570\u636e\u6e05\u6d17\u62a5\u544a\")\n        print(\"=\"*50)\n        \n        if 'missing_values' in self.cleaning_report:\n            print(\"\\n1. \u7f3a\u5931\u503c\u68c0\u6d4b:\")\n            if not self.cleaning_report&#91;'missing_values'].empty:\n                print(self.cleaning_report&#91;'missing_values'])\n            else:\n                print(\"  \u65e0\u7f3a\u5931\u503c\")\n        \n        if 'outliers' in self.cleaning_report:\n            print(\"\\n2. \u5f02\u5e38\u503c\u68c0\u6d4b:\")\n            for outlier_info in self.cleaning_report&#91;'outliers']:\n                print(f\"  {outlier_info&#91;'\u5217\u540d']}: {outlier_info&#91;'\u5f02\u5e38\u503c\u6570\u91cf']} \u4e2a\u5f02\u5e38\u503c \"\n                      f\"({outlier_info&#91;'\u5f02\u5e38\u503c\u6bd4\u4f8b%']}%)\")\n        \n        if 'duplicates' in self.cleaning_report:\n            print(\"\\n3. \u91cd\u590d\u503c\u68c0\u6d4b:\")\n            dup_info = self.cleaning_report&#91;'duplicates']\n            print(f\"  \u91cd\u590d\u884c\u6570: {dup_info&#91;'\u91cd\u590d\u884c\u6570']} \"\n                  f\"({dup_info&#91;'\u91cd\u590d\u6bd4\u4f8b%']}%)\")\n\n# \u8fd0\u884c\u6570\u636e\u6e05\u6d17\u793a\u4f8b\ndef run_data_cleaning_demo():\n    print(\"\\n\" + \"=\"*50)\n    print(\"\u6b65\u9aa43: \u6570\u636e\u6e05\u6d17\u6f14\u793a\")\n    print(\"=\"*50)\n    \n    # \u521b\u5efa\u6709\u95ee\u9898\u7684\u6d4b\u8bd5\u6570\u636e\n    np.random.seed(42)\n    test_data = pd.DataFrame({\n        'user_id': list(range(1001, 1011)) * 2,  # \u6545\u610f\u5236\u9020\u91cd\u590d\n        'age': &#91;25, 30, None, 35, 40, 200, 28, None, 32, 38, \n                25, 30, 22, 35, 40, 45, 28, 29, 32, 38],  # \u5305\u542b\u7f3a\u5931\u548c\u5f02\u5e38\n        'income': &#91;50000, 60000, 70000, None, 90000, \n                  100000, 55000, 65000, 75000, 85000] * 2,\n        'city': &#91;'\u5317\u4eac', '\u4e0a\u6d77', '\u5e7f\u5dde', '\u6df1\u5733', '\u676d\u5dde'] * 4,\n        'purchase_date': pd.date_range('2024-01-01', periods=20)\n    })\n    \n    print(\"\u539f\u59cb\u6570\u636e:\")\n    print(test_data.head())\n    print(f\"\u5f62\u72b6: {test_data.shape}\")\n    \n    # \u521d\u59cb\u5316\u6e05\u6d17\u5668\n    cleaner = DataCleaner()\n    \n    # 1. \u68c0\u6d4b\u7f3a\u5931\u503c\n    print(\"\\n1. \u7f3a\u5931\u503c\u68c0\u6d4b:\")\n    missing_df = cleaner.detect_missing_values(test_data)\n    if not missing_df.empty:\n        print(missing_df)\n    \n    # 2. \u5904\u7406\u7f3a\u5931\u503c\n    test_data_clean = cleaner.handle_missing_values(test_data, strategy='mean')\n    \n    # 3. \u68c0\u6d4b\u5f02\u5e38\u503c\n    print(\"\\n2. \u5f02\u5e38\u503c\u68c0\u6d4b:\")\n    outliers = cleaner.detect_outliers(test_data_clean, 'age')\n    if outliers is not None and len(outliers) &gt; 0:\n        print(f\"\u5e74\u9f84\u5f02\u5e38\u503c: {len(outliers)} \u4e2a\")\n        print(outliers&#91;&#91;'user_id', 'age']])\n    \n    # 4. \u5904\u7406\u5f02\u5e38\u503c\n    test_data_clean = cleaner.handle_outliers(test_data_clean, 'age', method='cap')\n    \n    # 5. \u68c0\u6d4b\u91cd\u590d\u503c\n    print(\"\\n3. \u91cd\u590d\u503c\u68c0\u6d4b:\")\n    duplicates = cleaner.detect_duplicates(test_data_clean, subset=&#91;'user_id'])\n    print(f\"\u91cd\u590d\u8bb0\u5f55\u6570: {len(duplicates)}\")\n    \n    # 6. \u5220\u9664\u91cd\u590d\u503c\n    test_data_clean = cleaner.remove_duplicates(test_data_clean, subset=&#91;'user_id'])\n    \n    # 7. \u6807\u51c6\u5316\u6570\u636e\u7c7b\u578b\n    type_map = {\n        'user_id': 'numeric',\n        'age': 'numeric',\n        'income': 'numeric',\n        'city': 'category',\n        'purchase_date': 'datetime'\n    }\n    test_data_clean = cleaner.standardize_data_types(test_data_clean, type_map)\n    \n    # 8. \u751f\u6210\u62a5\u544a\n    cleaner.generate_cleaning_report()\n    \n    print(\"\\n\u6e05\u6d17\u540e\u6570\u636e:\")\n    print(test_data_clean.head())\n    print(f\"\u5f62\u72b6: {test_data_clean.shape}\")\n    \n    return test_data_clean\n\nif __name__ == \"__main__\":\n    # \u8fd0\u884c\u5b8c\u6574\u793a\u4f8b\n    run_data_cleaning_demo()\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"%E5%AE%89%E8%A3%85%E8%A6%81%E6%B1%82\"><\/span><strong>\u5b89\u88c5\u8981\u6c42<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code># \u57fa\u7840\u4f9d\u8d56\npip install pandas==1.5.3 numpy==1.24.3 sqlalchemy==1.4.46 pymysql==1.0.2\npip install openpyxl==3.1.2 xlrd==2.0.1\n\n# \u53ef\u9009\uff1a\u6570\u636e\u53ef\u89c6\u5316\npip install matplotlib==3.7.1 seaborn==0.12.2<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>\u8bfe\u7a0b\u76ee\u6807 \u638c\u63e1\u4ece\u591a\u6e90\uff08Excel\u3001\u6570\u636e\u5e93\u3001API\uff09\u81ea\u52a8\u5316\u91c7\u96c6\u7535\u5546\u6570\u636e\uff0c\u5e76\u8fdb\u884c\u6807\u51c6\u5316\u6e05\u6d17\u3002 \u6838\u5fc3\u6280\u80fd &hellip; <a href=\"http:\/\/viplao.com\/index.php\/2026\/03\/01\/%e6%95%b0%e6%8d%ae%e6%8a%80%e8%83%bd%ef%bc%88skills%ef%bc%89-%ef%bc%9aday-4%ef%bc%9a%e6%95%b0%e6%8d%ae%e9%87%87%e9%9b%86%e4%b8%8e%e6%b8%85%e6%b4%97%e8%87%aa%e5%8a%a8%e5%8c%96\/\" class=\"more-link read-more\" rel=\"bookmark\">\u7ee7\u7eed\u9605\u8bfb <span class=\"screen-reader-text\">\u6570\u636e\u6280\u80fd\uff08SKILLS\uff09 \uff1aDay 4\uff1a\u6570\u636e\u91c7\u96c6\u4e0e\u6e05\u6d17\u81ea\u52a8\u5316<\/span><i class=\"fa fa-arrow-right\"><\/i><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[28],"views":141,"_links":{"self":[{"href":"http:\/\/viplao.com\/index.php\/wp-json\/wp\/v2\/posts\/4219"}],"collection":[{"href":"http:\/\/viplao.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/viplao.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/viplao.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/viplao.com\/index.php\/wp-json\/wp\/v2\/comments?post=4219"}],"version-history":[{"count":1,"href":"http:\/\/viplao.com\/index.php\/wp-json\/wp\/v2\/posts\/4219\/revisions"}],"predecessor-version":[{"id":4222,"href":"http:\/\/viplao.com\/index.php\/wp-json\/wp\/v2\/posts\/4219\/revisions\/4222"}],"wp:attachment":[{"href":"http:\/\/viplao.com\/index.php\/wp-json\/wp\/v2\/media?parent=4219"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/viplao.com\/index.php\/wp-json\/wp\/v2\/categories?post=4219"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/viplao.com\/index.php\/wp-json\/wp\/v2\/tags?post=4219"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}