SAS数组筛选瑞典市镇值失败求助:部分匹配异常问题排查
问题:SAS数组匹配瑞典市镇名失败,直接用IN列表却正常
我正在处理地理位置类自由文本回答,需判断回答是否属于本国290个瑞典市镇。为避免代码冗余,我将市镇名存入SAS数组,编写了如下代码:
Data resorTEST; keep R_res_ort_namn R_res_ort_txt R_kom_lan R_kommun; set resor1TEST resor2TEST resor3TEST; R_res_ort_namn=strip(lowcase(R_res_ort_namn)); R_res_ort_txt=strip(lowcase(R_res_ort_txt)); R_kom_lan=strip(lowcase(R_kom_lan)); array kommuner{290} $ ("upplands väsby" "vallentuna" "österåker" "värmdö" "järfälla" "ekerö" "huddinge" "botkyrka" "salem" "haninge" "tyresö" "upplands-bro" "nykvarn" "täby" "danderyd" "sollentuna" "stockholm" "södertälje" "nacka" "sundbyberg" "solna" "lidingö" "vaxholm" "norrtälje" "sigtuna" "nynäshamn" "håbo" "älvkarleby" "knivsta" "heby" "tierp" "uppsala" "enköping" "östhammar" "vingåker" "gnesta" "nyköping" "oxelösund" "flen" "katrineholm" "eskilstuna" "strängnäs" "trosa" "ödeshög" "ydre" "kinda" "boxholm" "åtvidaberg" "finspång" "valdemarsvik" "linköping" "norrköping" "söderköping" "motala" "vadstena" "mjölby" "aneby" "gnosjö" "mullsjö" "habo" "gislaved" "vaggeryd" "jönköping" "nässjö" "värnamo" "sävsjö" "vetlanda" "eksjö" "tranås" "uppvidinge" "lessebo" "tingsryd" "alvesta" "älmhult" "markaryd" "växjö" "ljungby" "högsby" "torsås" "mörbylånga" "hultsfred" "mönsterås" "emmaboda" "kalmar" "nybro" "oskarshamn" "västervik" "vimmerby" "borgholm" "gotland" "olofström" "karlskrona" "ronneby" "karlshamn" "sölvesborg" "svalöv" "staffanstorp" "burlöv" "vellinge" "östra göinge" "örkelljunga" "bjuv" "kävlinge" "lomma" "svedala" "skurup" "sjöbo" "hörby" "höör" "tomelilla" "bromölla" "osby" "perstorp" "klippan" "åstorp" "båstad" "malmö" "lund" "landskrona" "helsingborg" "höganäs" "eslöv" "ystad" "trelleborg" "kristianstad" "simrishamn" "ängelholm" "hässleholm" "hylte" "halmstad" "laholm" "falkenberg" "varberg" "kungsbacka" "härryda" "partille" "öckerö" "stenungsund" "tjörn" "orust" "sotenäs" "munkedal" "tanum" "dals-ed" "färgelanda" "ale" "lerum" "vårgårda" "bollebygd" "grästorp" "essunga" "karlsborg" "gullspång" "tranemo" "bengtsfors" "mellerud" "lilla edet" "mark" "svenljunga" "herrljunga" "vara" "götene" "tibro" "töreboda" "göteborg" "mölndal" "kungälv" "lysekil" "uddevalla" "strömstad" "vänersborg" "trollhättan" "alingsås" "borås" "ulricehamn" "åmål" "mariestad" "lidköping" "skara" "skövde" "hjo" "tidaholm" "falköping" "kil" "eda" "torsby" "storfors" "hammarö" "munkfors" "forshaga" "grums" "årjäng" "sunne" "karlstad" "kristinehamn" "filipstad" "hagfors" "arvika" "säffle" "lekeberg" "laxå" "hallsberg" "degerfors" "hällefors" "ljusnarsberg" "örebro" "kumla" "askersund" "karlskoga" "nora" "lindesberg" "skinnskatteberg" "surahammar" "kungsör" "hallstahammar" "norberg" "västerås" "sala" "fagersta" "köping" "arboga" "vansbro" "malung-sälen" "gagnef" "leksand" "rättvik" "orsa" "älvdalen" "smedjebacken" "mora" "falun" "borlänge" "säter" "hedemora" "avesta" "ludvika" "ockelbo" "hofors" "ovanåker" "nordanstig" "ljusdal" "gävle" "sandviken" "söderhamn" "bollnäs" "hudiksvall" "ånge" "timrå" "härnösand" "sundsvall" "kramfors" "sollefteå" "örnsköldsvik" "ragunda" "bräcke" "krokom" "strömsund" "åre" "berg" "härjedalen" "östersund" "nordmaling" "bjurholm" "vindeln" "robertsfors" "norsjö" "malå" "storuman" "sorsele" "dorotea" "vännäs" "vilhelmina" "åsele" "umeå" "lycksele" "skellefteå" "arvidsjaur" "arjeplog" "jokkmokk" "överkalix" "kalix" "övertorneå" "pajala" "gällivare" "älvsbyn" "luleå" "piteå" "boden" "haparanda" "kiruna"); /*if not missing(R_res_ort_namn) then R_kommun=prxchange("s/^.*-(.* kommun)/$1/",1,R_res_ort_namn); else if prxmatch("/^.*([a-zA-Z]*? kommun).*$/",R_res_ort_txt) then R_kommun=prxchange("s/^.*?([a-zA-Z]*? kommun).*$/$1/",-1,R_res_ort_txt); else if prxmatch("/^.*([a-zA-Z]*? kommun).*$/",R_kom_lan) then R_kommun=prxchange("s/^.*?([a-zA-Z]*? kommun).*$/$1/",-1,R_kom_lan); else */if R_res_ort_txt in kommuner then R_kommun=R_res_ort_txt; run;
测试发现部分市镇(如ängelholm)匹配失败,而直接将市镇列表放在IN运算符后则匹配正常。我已对变量执行strip去空格、lowcase转小写处理,请问问题出在哪里?
解决方法
问题核心是SAS字符数组的默认长度限制:
- 当你定义
array kommuner{290} $时,SAS默认给每个数组元素分配$8的长度。像ängelholm这类长度超过8的市镇名会被截断(变成ängelhol),自然匹配不上原字符串。 - 直接用IN列表时,SAS会自动识别每个字符串的完整长度,所以能正常匹配。
有两种修复方案:
方案一:指定数组元素的足够长度
修改数组定义行,给每个元素分配足够覆盖所有瑞典市镇名的长度,比如$20(瑞典最长的市镇名也远短于这个长度):
array kommuner{290} $20 ("upplands väsby" "vallentuna" "österåker" "värmdö" ... 后续市镇名保持不变 ... );
方案二:用数据集存储市镇名(更推荐)
把290个市镇名存入一个临时数据集,再通过proc sql或merge来匹配,避免数组长度的问题,也更便于维护:
- 先创建市镇数据集:
data kommuner_list; input kommun $20.; datalines; upplands väsby vallentuna österåker värmdö ... 其他所有市镇名 ... ; run;
- 用proc sql匹配:
proc sql; create table resorTEST as select a.*, b.kommun as R_kommun from ( select R_res_ort_namn, R_res_ort_txt, R_kom_lan from resor1TEST resor2TEST resor3TEST ) a left join kommuner_list b on strip(lowcase(a.R_res_ort_txt)) = strip(lowcase(b.kommun)); quit;
内容的提问来源于stack exchange,提问作者Magnus
相关产品推荐
相关产品推荐

