指南)
混合變量Mixed Variables是特征工程里一個很常見、但容易被忽略的問題。很多人做數(shù)據(jù)清洗時只檢查了缺失值、重復值、異常值卻忘了檢查某一列里是否同時混有數(shù)值和文本信息。等模型訓練報錯“could not convert string to float”時才回頭去看數(shù)據(jù)發(fā)現(xiàn)某一列里既有數(shù)字又有“Not Available”“High”“保密”這類文本或者某個字符串列里同時編碼了類別和數(shù)值信息。我之前在整理 CampusX 機器學習課程的筆記時也踩過這個坑。當時處理一份租金數(shù)據(jù)集Rent列看起來是數(shù)值型但str.contains(價格面議)查一下發(fā)現(xiàn)里面藏著文本BHK列看起來是分類但部分地區(qū)樣本寫成了“3 BHK”“2bhk”大小寫和空格都不統(tǒng)一。這類數(shù)據(jù)直接建模會出問題但直接丟棄又損失信息量。這篇文章就把混合變量識別的思路、處理策略和完整 Python 示例整理出來方便以后處理類似特征時直接參考。與其問“混合變量怎么處理”不如先問“這列數(shù)據(jù)里到底混了幾種信息”以及“拆解后哪種表示方式對模型最友好”。這篇文章會從概念、識別、處理到驗證完整走一遍。1. 混合變量核心概念速覽能力項說明項目背景機器學習特征工程環(huán)節(jié)源自 CampusX 課程中對特征處理方法的梳理核心問題數(shù)據(jù)列中同時包含數(shù)值信息和分類/文本信息直接建模會報錯或產(chǎn)生無效特征常見形式數(shù)值列混入文本標記分類列混入數(shù)值字符串中同時編碼數(shù)值和類別處理目標將混合變量拆解為代表數(shù)值信息、類別信息、缺失標記的干凈特征主要方法正則表達式文本提取、類型轉換、指示變量、頻率編碼、分箱、領域特征構造推薦工具Python、pandas、NumPy、re、scikit-learn適用平臺Windows / macOS / Linux 均可普通筆記本即可運行是否支持批量任務支持通過 pandas 向量化操作即可處理整列數(shù)據(jù)是否支持 API不涉及屬于離線數(shù)據(jù)處理流程可封裝為特征工程函數(shù)或 sklearn Transformer表格里簡化成一句話混合變量不是某種“錯誤數(shù)據(jù)”而是真實業(yè)務數(shù)據(jù)中常見的一種信息組織形式。處理它的核心思路是拆分、轉換、補全而不是簡單刪除。2. 適用場景與使用邊界混合變量處理屬于特征工程中的通用技能幾乎每個結構化數(shù)據(jù)分析項目都會碰到。最常見的場景有四個業(yè)務報表導出的數(shù)據(jù)。很多系統(tǒng)導出時會把數(shù)值和文本寫在同一個單元格里比如“12個月”“5年經(jīng)驗”“價格面議”這類數(shù)據(jù)進入 DataFrame 后會自動變成 object 類型。開放數(shù)據(jù)集的真實數(shù)據(jù)。Kaggle、天池這類平臺上很多真實數(shù)據(jù)集并不干凈類別列里會有拼寫變體、大小寫變體、帶單位或帶備注的文本。網(wǎng)頁爬取的數(shù)據(jù)。爬蟲抓到的數(shù)據(jù)往往把 HTML 文本和數(shù)字混在一起需要正則表達式統(tǒng)一提取。數(shù)據(jù)庫多源合并的數(shù)據(jù)。不同系統(tǒng)對同一字段的定義不一致有的存數(shù)值有的存文本合并后就會產(chǎn)生混合變量。但也有不適合處理、甚至不應該處理的情況目標列標簽列如果本身就是混合形式應該先做標簽統(tǒng)一和清洗而不是拆分后交給模型做多標簽。有些文本信息本質上屬于備注比如“客戶ID123電話456”這種信息需要先做數(shù)據(jù)脫敏和授權評估不能直接作為特征無腦放入模型。如果數(shù)據(jù)量極小比如只有幾十行特征工程帶來的收益有限優(yōu)先關注數(shù)據(jù)采集和標注質量問題。數(shù)據(jù)合規(guī)是一個不能跳過的問題。處理用戶信息、客戶數(shù)據(jù)、業(yè)務日志時涉及身份證號、手機號、地址、郵箱等個人敏感信息必須在脫敏后再進行特征工程涉及版權素材、商業(yè)數(shù)據(jù)、機密報表時需要確認是否有合法使用權。特征工程做的是“怎么讓模型用上數(shù)據(jù)”但前提是“這些數(shù)據(jù)能不能用”。3. 特征工程環(huán)境準備與前置條件本文的代碼只需要最基礎的數(shù)據(jù)科學環(huán)境。如果你的電腦上已經(jīng)有 Anaconda 或者 Python 3.8 以上的環(huán)境可以直接使用。建議先創(chuàng)建獨立環(huán)境避免與日常開發(fā)環(huán)境沖突conda create -n feature-engineering python3.10 -y conda activate feature-engineering然后安裝依賴庫pip install pandas numpy scikit-learn如果網(wǎng)絡下載比較慢可以使用國內鏡像源。pip install pandas numpy scikit-learn -i https://pypi.tuna.tsinghua.edu.cn/simple關于硬件這個主題和圖像、視頻模型完全不同CPU 就能跑不需要獨立顯卡也不需要大顯存。幾千行數(shù)據(jù)在普通筆記本上幾分鐘內就能完成全流程測試。需要說明的是混合變量處理不涉及模型訓練階段所以這里不討論 CUDA、GPU 加速、顯存占用等問題。如果你的數(shù)據(jù)量達到千萬行級別再考慮用 Polars、Dask 或 Spark 替代 pandas。4. 第一步混合變量的識別方法處理混合變量之前要先有能力發(fā)現(xiàn)它們。很多情況下我們不會刻意去查某一列是不是混合變量結果到建模階段才報錯。4.1 創(chuàng)建一份包含混合變量的示例數(shù)據(jù)為了演示這里構造一份模擬的員工薪資與履歷數(shù)據(jù)。數(shù)據(jù)中包含幾種典型的混合變量形態(tài)import pandas as pd import numpy as np data { employee_id: [E001, E002, E003, E004, E005, E006], salary: [25 LPA, 18 LPA, Not Disclosed, 12 LPA, 30 LPA, 保密], experience: [5 years, Fresher, 8 years, 2 years, 12 years, 6 年], qualification: [B.Tech, MCA, 12, PG, B.Tech, 10], age: [29, 25, 35, 28, 40, 保密], city: [Delhi, Mumbai, Bangalore, Pune, Delhi, Chennai] } df pd.DataFrame(data) print(df) print(\n列的數(shù)據(jù)類型) print(df.dtypes)輸出結果中salary、experience、qualification、age都是 object 類型但它們的“混合方式”各不相同salary是數(shù)值和單位混在一起部分行被替換成了“Not Disclosed”或“保密”。experience是數(shù)值和單位混在一起還存在中英文單位混用。qualification是分類列混入了數(shù)字“12”“10”很可能代表學歷年限或年級。age是數(shù)值列混入了文本“保密”。如果直接把這個 DataFrame 丟給 sklearn 模型訓練會直接報錯ValueError: could not convert string to float。這就是混合變量帶來的最直接問題。4.2 自動識別疑似混合變量對于較大的 DataFrame不可能每一列都手動看需要一個自動排查的思路。def find_mixed_columns(df, numeric_sample20): 初步標記可能存在混合變量的列。 思路對 object 列做非空值采樣嘗試轉數(shù)值如果轉失敗且失敗數(shù)量占比超過閾值 說明該列可能存在文本信息。 import re potential_mixed [] for col in df.columns: if df[col].dtype object: non_null df[col].dropna() if len(non_null) 0: continue sample non_null.sample(min(len(non_null), numeric_sample), random_state42) converted pd.to_numeric(sample, errorscoerce) fail_ratio converted.isna().mean() if fail_ratio 0.2: potential_mixed.append((col, round(fail_ratio, 2))) return potential_mixed print(find_mixed_columns(df))這段代碼的邏輯是object 列如果大部分能直接轉成數(shù)值則大概率是正常數(shù)值列如果有一部分無法轉數(shù)值就說明里面可能存在文本或特殊標記。它只是一個初步的“醫(yī)生分診”工具真正的判斷還是需要結合業(yè)務含義來確認。識別混合變量的另一個重要手段是查看唯一值for col in df.columns: print(f--- {col} ---) print(df[col].unique()[:20])用unique()查看每一列的非重復值能非常直觀地看到是不是有“數(shù)字和文本混在一起”的現(xiàn)象。5. 第二步混合變量的處理策略識別出混合變量之后接下來的問題就是怎么處理。這里按“信息類型”分為五類策略實際項目往往需要組合使用。5.1 文本提取法用正則表達式從字符串中提取數(shù)值信息對于“25 LPA”“5 years”“6 年”這類數(shù)據(jù)核心思路是提取出里面的數(shù)值部分。import re def extract_number(text): 從字符串中提取數(shù)字保留浮點數(shù)。 如果沒有數(shù)字返回 np.nan。 if pd.isna(text): return np.nan match re.search(r\d(\.\d)?, str(text)) if match: return float(match.group()) return np.nan df[salary_num] df[salary].apply(extract_number) df[experience_num] df[experience].apply(extract_number) print(df[[salary, salary_num, experience, experience_num]])對于salary來說“25 LPA”提取為 25.0“Not Disclosed”提取為 NaN。這樣數(shù)值信息就變成了可以進入模型的數(shù)值特征。這里要注意一個細節(jié)如果數(shù)據(jù)里有“12000 INR”這種數(shù)值和單位語義更強的字段簡單提取數(shù)字可能會導致量綱不一致。比如“12 LPA”提取為 12而“12000 per month”提取為 12000兩者不在一個量綱上。此時需要結合單位做換算。def parse_salary(text): 處理常見薪資寫法統(tǒng)一轉為 LPA每年十萬盧比。 注意這里的單位映射規(guī)則必須根據(jù)真實業(yè)務調整。 if pd.isna(text): return np.nan text str(text).lower() if not disclosed in text or 保密 in text: return np.nan match re.search(r(\d(\.\d)?), text) if not match: return np.nan value float(match.group(1)) if lpa in text or lakh in text: return value if k in text: return value / 100 if per month in text or /month in text: return value * 12 / 100000 return value df[salary_lpa] df[salary].apply(parse_salary) print(df[[salary, salary_lpa]])5.2 二元指示變量保留“是否存在信息”這個信號很多情況下salary為“Not Disclosed”或“保密”并不是缺失而是業(yè)務上的一種狀態(tài)。如果直接提取為 NaN模型就無法區(qū)分“數(shù)值缺失”和“員工選擇不披露”。處理方法是構造一個指示變量df[salary_not_disclosed] df[salary].apply( lambda x: 1 if (isinstance(x, str) and (not disclosed in x.lower() or 保密 in x)) else 0 ) print(df[[salary, salary_num, salary_not_disclosed]])這樣一個包含“不披露”狀態(tài)的薪資列就被拆成了兩個特征salary_num數(shù)值信息缺失時用NaN或填充值。salary_not_disclosed是否不披露1 表示有明確文本標記。這個思路同樣適用于其他場景比如“年齡保密”“價格面議”“電話未提供”等。指示變量的價值在于它把“文本標記”轉換成模型能直接使用的 0/1 信息而不是把所有非數(shù)值信息都當作缺失值處理。這類特征往往能提升模型在特定業(yè)務場景下的表現(xiàn)。5.3 類型轉換與分類編碼處理分類列中的混雜信息qualification這列的典型問題是“B.Tech”“MCA” 等分類標簽和 “12”“10” 這類數(shù)字混在一起。如果數(shù)字代表學歷年限可以有兩種處理方式方式一把數(shù)字映射成明確的分類標簽。qualification_map { 10: Secondary, 12: Higher Secondary, B.Tech: Bachelor, MCA: Master, PG: Master } df[qualification_label] df[qualification].map(qualification_map) print(df[[qualification, qualification_label]])方式二直接對原始列做 One-Hot 編碼把“12”“10”也視為合法類別。這種方法簡單但會丟失學歷層級順序。5.4 順序特征的映射編碼有些混合變量雖然看起來是字符串但內部存在可比較的順序比如“Fresher”“Junior”“Senior”“Lead”這類等級。類比到機器學習競賽中常見的是“Graduate”“Post Graduate”“Doctorate”它們之間存在明顯的次序關系。level_map { Fresher: 0, Junior: 1, Senior: 2, Lead: 3, Manager: 4 } df[experience_level] df[experience].map(level_map) print(df[[experience, experience_level]])如果原始數(shù)據(jù)是“5 years”“8 years”這種連續(xù)數(shù)值可以直接用提取出的experience_num如果數(shù)據(jù)里混有“Fresher”“Senior”這類等級標簽就需要先把它們映射為有序數(shù)值再和其他數(shù)值型經(jīng)驗特征做整合。順序映射的關鍵在于映射規(guī)則必須反映業(yè)務語義。比如“Fresher”為 0“5 years”提取為 5那“Junior”應該映射為 1 還是 2需要先和業(yè)務方確認不能拍腦袋。5.5 頻率編碼處理高基數(shù)分類變量有時候混合變量本身沒有太多需要拆解的信息但類別數(shù)量很多比如“city”列有幾十個城市直接 One-Hot 會產(chǎn)生大量稀疏列。這時候可以考慮頻率編碼。city_freq df[city].value_counts(normalizeTrue) df[city_freq] df[city].map(city_freq) print(df[[city, city_freq]])頻率編碼的思路是“出現(xiàn)頻次越高的類別在數(shù)據(jù)中的普遍程度越高”用頻次代替類別標簽可以壓縮維度同時保留類別分布信息。不過頻率編碼容易過擬合尤其在小數(shù)據(jù)集上。建議在訓練集上計算頻率再把映射關系應用到驗證集和測試集避免數(shù)據(jù)泄漏。6. 第三步完整代碼演示與效果驗證前面每一步都是零散的這里把完整流程串起來從原始 DataFrame 到可建模的特征矩陣一步到位。6.1 完整特征工程代碼import pandas as pd import numpy as np import re from sklearn.model_selection import train_test_split from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import accuracy_score, classification_report # 1. 構造模擬數(shù)據(jù) data { employee_id: [E001, E002, E003, E004, E005, E006], salary: [25 LPA, 18 LPA, Not Disclosed, 12 LPA, 30 LPA, 保密], experience: [5 years, Fresher, 8 years, 2 years, 12 years, 6 年], qualification: [B.Tech, MCA, 12, PG, B.Tech, 10], age: [29, 25, 35, 28, 40, 保密], city: [Delhi, Mumbai, Bangalore, Pune, Delhi, Chennai], promoted: [1, 0, 1, 0, 1, 0] } df pd.DataFrame(data) # 2. 從 salary 中提取數(shù)值和單位 def parse_salary(text): if pd.isna(text): return np.nan text str(text).lower() if not disclosed in text or 保密 in text: return np.nan match re.search(r(\d(\.\d)?), text) if not match: return np.nan value float(match.group(1)) if lpa in text or lakh in text: return value if k in text: return value / 100 if per month in text or /month in text: return value * 12 / 100000 return value df[salary_lpa] df[salary].apply(parse_salary) # 3. 構造“未披露”指示變量 df[salary_not_disclosed] df[salary].apply( lambda x: 1 if (isinstance(x, str) and (not disclosed in x.lower() or 保密 in x)) else 0 ) # 4. 從 experience 中提取數(shù)值 def extract_exp_num(text): if pd.isna(text): return np.nan text str(text).lower() if fresher in text: return 0 match re.search(r(\d(\.\d)?), text) if match: return float(match.group(1)) return np.nan df[experience_num] df[experience].apply(extract_exp_num) # 5. qualification 映射 qualification_map { 10: 0, 12: 1, B.Tech: 2, MCA: 3, PG: 3 } df[qualification_level] df[qualification].map(qualification_map) # 6. age 列的保密標記 df[age_not_disclosed] df[age].apply(lambda x: 1 if x 保密 else 0) df[age_num] pd.to_numeric(df[age], errorscoerce) # 7. city 頻率編碼 city_freq df[city].value_counts(normalizeTrue) df[city_freq] df[city].map(city_freq) # 8. 選擇建模特征 features [ salary_lpa, salary_not_disclosed, experience_num, qualification_level, age_num, age_not_disclosed, city_freq ] model_df df[features].fillna({ salary_lpa: 0, experience_num: 0, age_num: 0 }) # 9. 建模驗證 X model_df y df[promoted] X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.4, random_state42, stratifyy ) model RandomForestClassifier(n_estimators50, random_state42) model.fit(X_train, y_train) y_pred model.predict(X_test) print(Accuracy:, accuracy_score(y_test, y_pred)) print(classification_report(y_test, y_pred))這個完整流程覆蓋了前面講的五種核心策略正則提取從salary、experience中提取數(shù)值。指示變量標記“未披露”和“保密”這類業(yè)務狀態(tài)。業(yè)務映射把學歷映射為等級。缺失補充用 0 填充提取失敗的數(shù)值字段。頻率編碼處理城市這類高基數(shù)分類變量。6.2 效果驗證思路在小規(guī)模模擬數(shù)據(jù)上模型準確率只是一個演示結果。更重要的驗證方式是比較“處理前”和“處理后”的建模效果處理前直接對原始 DataFrame 建模會報錯這是最直觀的驗證。處理后模型能正常訓練并且可以輸出分類報告。如果你有真實業(yè)務數(shù)據(jù)建議用同樣的特征工程流程跑一遍然后用特征重要性和邏輯回歸系數(shù)來驗證每個新特征是否有效。比如salary_not_disclosed特征如果重要度很高說明“是否披露薪資”本身對業(yè)務結果有較強的區(qū)分能力。6.3 判斷特征工程是否成功的標準特征工程做得好不好不是看代碼跑通沒有而是看以下幾點模型輸入中沒有出現(xiàn)字符串報錯。處理后的特征在業(yè)務上有明確含義能向業(yè)務方解釋清楚。訓練集和驗證集的特征分布一致。特征數(shù)量控制在可解釋范圍內沒有出現(xiàn)高維稀疏爆炸。新數(shù)據(jù)輸入時特征工程函數(shù)可以無縫復用。如果這五條都滿足特征工程這部分基本合格。7. 常見問題與排查方法混合變量處理過程中會遇到不少問題這里整理成表格方便排查。問題現(xiàn)象可能原因排查方式解決方案pd.to_numeric轉換后全是 NaN文本格式太雜正則匹配范圍不足打印該列所有唯一值檢查正則覆蓋情況增加正則分支或先做文本歸一化提取出的數(shù)字量綱不一致數(shù)據(jù)中單位不統(tǒng)一月薪/年薪/萬/千查看單位關鍵詞分布先統(tǒng)一單位再做數(shù)值提取模型依然無法訓練仍有字符串列未處理檢查df.dtypes確認沒有 object 類型對剩余 object 列再做編碼或刪除缺失值處理不當導致信息丟失把“未披露”直接當作缺失值處理統(tǒng)計“未披露”文本的數(shù)量構造二元指示變量再填充缺失值One-Hot 編碼后維度爆炸分類列類別過多查看nunique()改用頻率編碼、目標編碼或 Embedding訓練集和測試集頻率編碼不一致在合并數(shù)據(jù)上計算頻率或測試集有未知類別檢查映射字典是否覆蓋全部類別在訓練集上計算頻率未知類別填充為 0特征工程代碼無法復用到新數(shù)據(jù)函數(shù)依賴了全局變量或單次數(shù)據(jù)的內容檢查函數(shù)是否對輸入數(shù)據(jù)有強依賴封裝為函數(shù)輸入 DataFrame輸出增強后的 DataFrame正則提取把錯誤文本提取成數(shù)字數(shù)據(jù)中存在和業(yè)務無關的數(shù)字如 ID 號查看提取結果是否明顯不合邏輯增加單位/關鍵詞約束或結合前后文本判斷中文和英文單位混用多語言數(shù)據(jù)來源統(tǒng)一轉小寫后再匹配構建中英文單位同義詞表分類列中混入數(shù)字但無法判斷含義缺少數(shù)據(jù)字典找數(shù)據(jù)提供方確認數(shù)字含義先作為獨立類別處理后續(xù)再映射在這個表中最值得注意的問題是“文本格式太雜導致正則覆蓋不全”。真實數(shù)據(jù)往往比模擬數(shù)據(jù)更臟可能同時存在“25LPA”“25 LPA”“Rs. 25 LPA”“25 LPA (Negotiable)”等多種寫法。建議先做文本歸一化統(tǒng)一大小寫、去空格、替換常見縮寫再寫提取正則。8. 最佳實踐與工程化建議特征工程在實際項目中不是一次性的它需要被反復使用在訓練、驗證、測試和線上推理流程中。以下經(jīng)驗來自常見的結構化數(shù)據(jù)項目實踐可以直接參考。8.1 封裝特征工程函數(shù)不要在每個 Notebook 里復制粘貼同一步處理邏輯把清洗流程封裝成函數(shù)或 sklearn Pipeline。def clean_salary_feature(df, colsalary): df df.copy() df[salary_lpa] df[col].apply(parse_salary) df[salary_not_disclosed] df[col].apply( lambda x: 1 if (isinstance(x, str) and (not disclosed in x.lower() or 保密 in x)) else 0 ) return df # 訓練數(shù)據(jù)和線上推理都可以復用 train_df clean_salary_feature(train_df) test_df clean_salary_feature(test_df)如果使用 scikit-learn可以把這些步驟封裝成自定義 Transformer再和ColumnTransformer組合成完整 Pipeline。這樣網(wǎng)格搜索、交叉驗證、模型導出都會更規(guī)范。8.2 保留原始數(shù)據(jù)處理結果單獨存儲特征工程過程中原始數(shù)據(jù)絕對不能覆蓋。建議把處理后的特征單獨保存一份例如輸出成新的 parquet、feather 或 CSV 文件。df.to_csv(processed_feature_data.csv, indexFalse)這樣做的好處是如果后發(fā)現(xiàn)某一步特征構造有 bug可以回到原始數(shù)據(jù)重新處理而不必重新找數(shù)據(jù)。8.3 特征構建過程留下文檔每一個新特征都應該記錄三件事特征名稱和數(shù)據(jù)類型。處理邏輯正則規(guī)則、映射規(guī)則、填充規(guī)則。創(chuàng)建日期和創(chuàng)建原因。例如特征名類型構建邏輯說明salary_lpafloat正則提取數(shù)字統(tǒng)一轉 LPA提取自 salary 原始列salary_not_disclosedint(0/1)判斷是否存在“Not Disclosed”保留信息缺失狀態(tài)experience_numfloat正則提取數(shù)字Fresher 映射為 0提取自 experiencequalification_levelint字典映射學歷等級學歷有序化有文檔的特征工程才具備可維護性尤其當項目交接或半年后再回來看時文檔能省下大量時間。8.4 防止數(shù)據(jù)泄漏頻率編碼和順序映射的規(guī)則只能基于訓練集計算然后通過映射字典應用到驗證集和測試集。如果先對全量數(shù)據(jù)做value_counts再切分訓練集和測試集會造成評估指標虛高。city_freq_train train_df[city].value_counts(normalizeTrue) train_df[city_freq] train_df[city].map(city_freq_train) test_df[city_freq] test_df[city].map(city_freq_train).fillna(0)8.5 區(qū)分缺失值和業(yè)務狀態(tài)混合變量處理中最容易犯的錯誤是把“Not Disclosed”“保密”“價格面議”這類文本和真正的缺失值混為一談。它們在業(yè)務上的含義完全不同真正缺失可能是數(shù)據(jù)采集漏了而“保密/面議”是一個離散狀態(tài)代表用戶主動不披露或數(shù)據(jù)無法提供。建議先做指示變量再考慮填充策略。8.6 數(shù)據(jù)合規(guī)與隱私保護處理用戶數(shù)據(jù)、客戶信息、企業(yè)數(shù)據(jù)時要謹慎對待個人敏感信息。手機號、身份證號、詳細地址、精確地理位置等字段不應該作為特征直接進入模型。如果必須使用必須經(jīng)過脫敏、泛化或加密處理并確認數(shù)據(jù)來源合法、使用目的合規(guī)。特征工程不能成為繞過隱私保護的借口。9. 總結與下一步混合變量處理是機器學習特征工程中非?;A、但非常實用的一環(huán)。處理邏輯清晰五步可以走完先識別是否存在混合變量再判斷列中混合了哪幾種信息接著按信息類型拆分然后構造指示變量保留業(yè)務狀態(tài)最后按需編碼并驗證模型效果。從我的經(jīng)驗看最容易踩的坑有兩個。第一是把“Not Disclosed”“保密”這類業(yè)務狀態(tài)直接當作缺失值填充導致信息丟失。第二是在沒有檢查唯一值的情況下直接訓練模型等報錯才發(fā)現(xiàn)有些列是 object 類型。這兩類問題在真實數(shù)據(jù)集中非常常見處理成本也不高關鍵是要在特征工程階段預留時間做數(shù)據(jù)排查。建議你拿到一份新數(shù)據(jù)集后先執(zhí)行一次df.dtypes和df[col].unique()全列檢查把混合變量標記出來再用這篇文章里的函數(shù)逐個處理。第一次先跑通流程后面再逐步完善單位映射和填充策略。把這套處理流程沉淀成自己的特征工程函數(shù)庫以后做 Kaggle、天池或實際業(yè)務項目時都能直接復用。下一步可以繼續(xù)深入的方向是目標編碼和貝葉斯編碼當類別列包含混合信息、而且類別數(shù)量和標簽之間有明顯關聯(lián)時這兩類編碼會比 One-Hot 和頻率編碼更有效。不過在那之前先把混合變量識別與拆分練熟因為這是所有編碼方法的基礎。