
在SAS中如何解決中文亂碼問題
在日常的數(shù)據(jù)分析處理工作中,不可避免的經(jīng)常會(huì)和中文字符串打交道。如果數(shù)據(jù)中有亂碼,該如何處理?...
在日常工作中,使用SAS進(jìn)行數(shù)據(jù)處理是很正常的事情,不可避免的經(jīng)常會(huì)和中文字符串打交道。不知道各位在使用EG的過程中,打開數(shù)據(jù)集查看數(shù)據(jù)的時(shí)候,有沒有遇到過以下問題?
(雖然我也只是偶爾遇到,但已經(jīng)被折磨好幾年?。?
SAS Enterprise Guide 5.1
SAS Enterprise Guide 6.1
SAS Enterprise Guide 7.1
不同的版本提示的錯(cuò)誤形式不完全一樣,但出現(xiàn)的原因卻是一模一樣的(下面有情景再現(xiàn)的過程)。仔細(xì)查看,不難發(fā)現(xiàn)真正的錯(cuò)誤信息都是一樣的,主要是:
“Failed to transcode data from U_EUC_CN_CE to U_UTF8_CE encoding because it contained characters wihch are not supported by your SAS session encoding. Please review your encoding= and locale= SAS system options to ensure that they can accommodate tje data that you want to process.”
這段話是什么意思呢?其實(shí)就是上面EG 7.1版本的錯(cuò)誤提示的中文描述。簡(jiǎn)而言之,就是告訴你數(shù)據(jù)中有無法處理的編碼數(shù)據(jù)。
出現(xiàn)這個(gè)問題,僅僅是不能打開查看數(shù)據(jù)嗎?不是!如果出現(xiàn)這個(gè)問題,意味著你基本不能用這個(gè)數(shù)據(jù)進(jìn)行后續(xù)的分析了。只要進(jìn)行的處理或者分析涉及到該有問題的字段就會(huì)提示上面的這個(gè)錯(cuò)誤信息,陰魂不散,揮之不去。
最簡(jiǎn)單粗暴的辦法就是不用圖形化的工具EG,用最經(jīng)典的Base工具就沒有這個(gè)問題了,一勞永逸。而有時(shí)候沒法不用EG的時(shí)候怎么辦?比如我是用EG連著SAS服務(wù)器進(jìn)行處理的,該怎么辦?
至于為什么EG會(huì)出現(xiàn)這個(gè)問題,而Base界面沒有這個(gè)問題呢?主要是因?yàn)檐浖牡讓釉O(shè)計(jì)而導(dǎo)致的,這個(gè)編碼問題說大不大,說小不?。缓雎粤司涂梢哉J褂?,如果不忽略,那么它就是一個(gè)問題。下面會(huì)對(duì)這個(gè)問題進(jìn)行再現(xiàn),剖析其原因,你就明白了。
當(dāng)我第一次遇到這個(gè)問題的時(shí)候,想不明白,就去google搜索錯(cuò)誤信息,找到的文檔資料基本都是說編碼或者地區(qū)的設(shè)置問題。意思就是說數(shù)據(jù)的編碼跟現(xiàn)有的SAS環(huán)境的編碼不一致,也就是上面錯(cuò)誤信息當(dāng)中提示的。要你通過option encoding= locale=; 修改到正確的編碼及地區(qū),就可以解決問題了??墒俏业沫h(huán)境是沒有任何問題的,數(shù)據(jù)也是同樣的環(huán)境生成的。經(jīng)過了幾次的研究,最后搞清楚了,這個(gè)問題是由于中文被截?cái)喽鴮?dǎo)致的。
(下文需要有一定的IT基礎(chǔ)知識(shí),不懂的童鞋,可度娘有關(guān)數(shù)據(jù)存儲(chǔ)、數(shù)據(jù)編碼方面的知識(shí);只要大概明白數(shù)據(jù)是怎么在計(jì)算機(jī)中存儲(chǔ)及還原的就OK了)
具體來說:在GBK編碼中(SAS中文的默認(rèn)編碼方式),一個(gè)漢字是占兩個(gè)字節(jié)。由于各種原因,在存儲(chǔ)數(shù)據(jù)的時(shí)候某個(gè)漢字只存儲(chǔ)了其中的一個(gè)字節(jié),另一個(gè)字節(jié)丟失了。那么就導(dǎo)致這個(gè)字節(jié)沒法還原,不知道是什么東西(因?yàn)樯僖粋€(gè)字節(jié)的信息)。所以才會(huì)有上面的錯(cuò)誤提示:數(shù)據(jù)中包含當(dāng)前SAS會(huì)話編碼不支持的編碼數(shù)據(jù)。
我們可以用下面簡(jiǎn)單的程序來再現(xiàn)這個(gè)問題(在EG中運(yùn)行這段程序,在Base中是可以正常查看數(shù)據(jù)的,但只顯示“你好”。)
data test;
length str $ 5;
str="你好啊";
run;
當(dāng)運(yùn)行完這段程序,打開test數(shù)據(jù)集查看的時(shí)候,就出現(xiàn)上面的錯(cuò)誤信息:
“你好啊”三個(gè)漢字需要6個(gè)字節(jié)去存儲(chǔ),而str事先定義了長(zhǎng)度為5個(gè)字節(jié),這就導(dǎo)致只存儲(chǔ)了2.5個(gè)漢字;而存儲(chǔ)的這0.5個(gè)漢字信息由于沒法顯示,所以才導(dǎo)致上面提示的編碼問題。
進(jìn)一步來看看底層的信息(十六進(jìn)制編碼):
data _null_;
length str1 $ 5 str2 $ 6;
str1="你好啊";
str2="你好啊";
put str1 $hex12.;
put str2 $hex12.;
run;
日志信息:
從上面的日志信息可以看到,就是因?yàn)樯俅鎯?chǔ)了“A1”這個(gè)字節(jié)信息,導(dǎo)致“B0”這個(gè)字節(jié)無法解碼,無法正常顯示。
額外補(bǔ)充(懂的人就此略過):
漢字“你”的GBK編碼,十進(jìn)制為50403,十六進(jìn)制為C4E3
漢字“好”的GBK編碼,十進(jìn)制為47811,十六進(jìn)制為BAC3
漢字“啊”的GBK編碼,十進(jìn)制為45217,十六進(jìn)制為B0A1有人可能會(huì)想:英文字符就是一個(gè)字節(jié)存儲(chǔ)的,一個(gè)字節(jié)也能顯示出來;為什么這里的一個(gè)字節(jié)就出問題了?
這就涉及到編碼范圍的問題了,英文字符是ASCII編碼。通過查看標(biāo)準(zhǔn)的ASCII碼表就可發(fā)現(xiàn),最大的編碼十進(jìn)制為127,十六進(jìn)制為7F;而B0是遠(yuǎn)大于7F的,超出了ASCII的編碼范圍,因此無法顯示。
如果你夠仔細(xì),你就會(huì)發(fā)現(xiàn),其實(shí)在EG的錯(cuò)誤提示中,就包含了這段出問題的十六進(jìn)制編碼信息:c4 e3 ba c3 b0。
問題的原因既然搞清楚了,那么如何解決的思路就很清晰了。說白了就是找出字符串中有中文截?cái)嗟牡胤?,然后將這半個(gè)漢字的信息直接刪除就沒問題了。
以前面生成的test數(shù)據(jù)為例,str的最后一個(gè)字節(jié)包含了半個(gè)漢字信息,只要將最后一個(gè)字節(jié)刪掉就OK了。
data test2;
set test;
code_before=put(str,$hex10.);
str=substr(str,1,4);
code_after=put(str,$hex10.);
run;
如上所示,經(jīng)過處理后,可以正常的顯示數(shù)據(jù)了。
(注:code_after中最后一個(gè)字節(jié)“20”是空格的十六進(jìn)制編碼。字符變量中多余的字節(jié),SAS默認(rèn)用空格來填充。因此“你好”兩個(gè)漢字占4個(gè)字節(jié),剩余一個(gè)字節(jié)就是空格。)
雖然解決方法很清晰,想起來也很簡(jiǎn)單,但要實(shí)現(xiàn)起來還不是那么容易。上面的情況是特例,我們明顯知道在哪個(gè)地方有問題,直接處理就OK。
但通常情況下,我們是不知道在字符串的具體哪個(gè)地方有截?cái)?,也不知道是哪些觀測(cè)有截?cái)嗟膯栴};而且每條觀測(cè)中被截?cái)嗟奈恢靡膊灰欢ǘ家粯?,甚至也不知道截?cái)嗟臄?shù)據(jù)后面有沒有其他字符數(shù)據(jù)。面對(duì)這么多不確定,該如何解決?
下面,提供一種思路,有興趣的童鞋可以自由發(fā)揮,去解決這個(gè)問題。
首先,GBK編碼方案中,總體的編碼是有范圍的,從8140~FEFE。其中首字節(jié)在81~FE之間,尾字節(jié)在40~FE之間,剔除xx7F一條線;總計(jì)23940個(gè)碼位,共收入21886個(gè)漢字和圖形符號(hào),其中漢字21003個(gè),圖形符號(hào)883個(gè)。
其次,ASCII編碼的范圍是從00~7F,共計(jì)128個(gè)碼位,收入大小寫英文字母、數(shù)字、符號(hào)、及特殊控制字符。其中可顯示的編碼范圍為20~7E。
基于上面的這些信息,就可以從十六進(jìn)制編碼入手,逐個(gè)去判斷識(shí)別,進(jìn)而找到存在截?cái)嗟奈恢?,然后將其處理掉。記得要考慮以下多種情況:數(shù)據(jù)分析師培訓(xùn)
截?cái)嗲闆r出現(xiàn)在字符串末尾
截?cái)嗲闆r出現(xiàn)在字符串中間,且后面緊跟英文字母
截?cái)嗲闆r出現(xiàn)在字符串中間,且后面緊跟完整的漢字
推薦學(xué)習(xí)書籍
《CDA一級(jí)教材》適合CDA一級(jí)考生備考,也適合業(yè)務(wù)及數(shù)據(jù)分析崗位的從業(yè)者提升自我。完整電子版已上線CDA網(wǎng)校,累計(jì)已有10萬+在讀~
免費(fèi)加入閱讀:https://edu.cda.cn/goods/show/3151?targetId=5147&preview=0
數(shù)據(jù)分析咨詢請(qǐng)掃描二維碼
若不方便掃碼,搜微信號(hào):CDAshujufenxi
SQL Server 中 CONVERT 函數(shù)的日期轉(zhuǎn)換:從基礎(chǔ)用法到實(shí)戰(zhàn)優(yōu)化 在 SQL Server 的數(shù)據(jù)處理中,日期格式轉(zhuǎn)換是高頻需求 —— 無論 ...
2025-09-18MySQL 大表拆分與關(guān)聯(lián)查詢效率:打破 “拆分必慢” 的認(rèn)知誤區(qū) 在 MySQL 數(shù)據(jù)庫管理中,“大表” 始終是性能優(yōu)化繞不開的話題。 ...
2025-09-18CDA 數(shù)據(jù)分析師:表結(jié)構(gòu)數(shù)據(jù) “獲取 - 加工 - 使用” 全流程的賦能者 表結(jié)構(gòu)數(shù)據(jù)(如數(shù)據(jù)庫表、Excel 表、CSV 文件)是企業(yè)數(shù)字 ...
2025-09-18DSGE 模型中的 Et:理性預(yù)期算子的內(nèi)涵、作用與應(yīng)用解析 動(dòng)態(tài)隨機(jī)一般均衡(Dynamic Stochastic General Equilibrium, DSGE)模 ...
2025-09-17Python 提取 TIF 中地名的完整指南 一、先明確:TIF 中的地名有哪兩種存在形式? 在開始提取前,需先判斷 TIF 文件的類型 —— ...
2025-09-17CDA 數(shù)據(jù)分析師:解鎖表結(jié)構(gòu)數(shù)據(jù)特征價(jià)值的專業(yè)核心 表結(jié)構(gòu)數(shù)據(jù)(以 “行 - 列” 規(guī)范存儲(chǔ)的結(jié)構(gòu)化數(shù)據(jù),如數(shù)據(jù)庫表、Excel 表、 ...
2025-09-17Excel 導(dǎo)入數(shù)據(jù)含缺失值?詳解 dropna 函數(shù)的功能與實(shí)戰(zhàn)應(yīng)用 在用 Python(如 pandas 庫)處理 Excel 數(shù)據(jù)時(shí),“缺失值” 是高頻 ...
2025-09-16深入解析卡方檢驗(yàn)與 t 檢驗(yàn):差異、適用場(chǎng)景與實(shí)踐應(yīng)用 在數(shù)據(jù)分析與統(tǒng)計(jì)學(xué)領(lǐng)域,假設(shè)檢驗(yàn)是驗(yàn)證研究假設(shè)、判斷數(shù)據(jù)差異是否 “ ...
2025-09-16CDA 數(shù)據(jù)分析師:掌控表格結(jié)構(gòu)數(shù)據(jù)全功能周期的專業(yè)操盤手 表格結(jié)構(gòu)數(shù)據(jù)(以 “行 - 列” 存儲(chǔ)的結(jié)構(gòu)化數(shù)據(jù),如 Excel 表、數(shù)據(jù) ...
2025-09-16MySQL 執(zhí)行計(jì)劃中 rows 數(shù)量的準(zhǔn)確性解析:原理、影響因素與優(yōu)化 在 MySQL SQL 調(diào)優(yōu)中,EXPLAIN執(zhí)行計(jì)劃是核心工具,而其中的row ...
2025-09-15解析 Python 中 Response 對(duì)象的 text 與 content:區(qū)別、場(chǎng)景與實(shí)踐指南 在 Python 進(jìn)行 HTTP 網(wǎng)絡(luò)請(qǐng)求開發(fā)時(shí)(如使用requests ...
2025-09-15CDA 數(shù)據(jù)分析師:激活表格結(jié)構(gòu)數(shù)據(jù)價(jià)值的核心操盤手 表格結(jié)構(gòu)數(shù)據(jù)(如 Excel 表格、數(shù)據(jù)庫表)是企業(yè)最基礎(chǔ)、最核心的數(shù)據(jù)形態(tài) ...
2025-09-15Python HTTP 請(qǐng)求工具對(duì)比:urllib.request 與 requests 的核心差異與選擇指南 在 Python 處理 HTTP 請(qǐng)求(如接口調(diào)用、數(shù)據(jù)爬取 ...
2025-09-12解決 pd.read_csv 讀取長(zhǎng)浮點(diǎn)數(shù)據(jù)的科學(xué)計(jì)數(shù)法問題 為幫助 Python 數(shù)據(jù)從業(yè)者解決pd.read_csv讀取長(zhǎng)浮點(diǎn)數(shù)據(jù)時(shí)的科學(xué)計(jì)數(shù)法問題 ...
2025-09-12CDA 數(shù)據(jù)分析師:業(yè)務(wù)數(shù)據(jù)分析步驟的落地者與價(jià)值優(yōu)化者 業(yè)務(wù)數(shù)據(jù)分析是企業(yè)解決日常運(yùn)營(yíng)問題、提升執(zhí)行效率的核心手段,其價(jià)值 ...
2025-09-12用 SQL 驗(yàn)證業(yè)務(wù)邏輯:從規(guī)則拆解到數(shù)據(jù)把關(guān)的實(shí)戰(zhàn)指南 在業(yè)務(wù)系統(tǒng)落地過程中,“業(yè)務(wù)邏輯” 是連接 “需求設(shè)計(jì)” 與 “用戶體驗(yàn) ...
2025-09-11塔吉特百貨孕婦營(yíng)銷案例:數(shù)據(jù)驅(qū)動(dòng)下的精準(zhǔn)零售革命與啟示 在零售行業(yè) “流量紅利見頂” 的當(dāng)下,精準(zhǔn)營(yíng)銷成為企業(yè)突圍的核心方 ...
2025-09-11CDA 數(shù)據(jù)分析師與戰(zhàn)略 / 業(yè)務(wù)數(shù)據(jù)分析:概念辨析與協(xié)同價(jià)值 在數(shù)據(jù)驅(qū)動(dòng)決策的體系中,“戰(zhàn)略數(shù)據(jù)分析”“業(yè)務(wù)數(shù)據(jù)分析” 是企業(yè) ...
2025-09-11Excel 數(shù)據(jù)聚類分析:從操作實(shí)踐到業(yè)務(wù)價(jià)值挖掘 在數(shù)據(jù)分析場(chǎng)景中,聚類分析作為 “無監(jiān)督分組” 的核心工具,能從雜亂數(shù)據(jù)中挖 ...
2025-09-10統(tǒng)計(jì)模型的核心目的:從數(shù)據(jù)解讀到?jīng)Q策支撐的價(jià)值導(dǎo)向 統(tǒng)計(jì)模型作為數(shù)據(jù)分析的核心工具,并非簡(jiǎn)單的 “公式堆砌”,而是圍繞特定 ...
2025-09-10