2014-04-18 97 views
6

我有一個數據庫,其中包含我正在讀入R(3.02)的英超足球運動員的名字,但遇到困難時,他們的名字中帶有外國字符的球員(變音符號,口音等)。下面的代碼說明了這一點:閱讀外國字符

PlayerData<-read.table("C:\\Users\\Documents\\Players.csv",quote=NULL, dec = ".",,sep=",", stringsAsFactors=F,header=T,fill=T,blank.lines.skip = TRUE) 
Test<-PlayerData[c(33655:33656),] #names of the players here are "Cazorla" "Özil" 

Test[Test$Player=="Cazorla",] #Outputs correct details 
Test[Test$Player=="Ozil",] # Can not find data '0 rows> (or 0-length row.names)' 
< 

#Example of how the foreign character is treated: 
substr("Özil",1,1) 
[1] "Ã" 
substr("Özil",1,2) 
[1] "Ö" 
substr("Özil",2,2) 
[1] " 
substr("Özil",2,3) 
[1] "z 

我試圖替換字符,如下所述:R: Replacing foreign characters in a string,但在我的例子重音字符出現應該被理解成兩個不同的角色,我不認爲它的工作原理。

我將不勝感激任何建議或解決方法。

該文件可供下載here

+0

你可以把你的CSV的兩行放在網上的某個地方嗎?也許'iconv'可以提供幫助。 –

+1

這需要更長的答案(其中大部分答案不在我的專業範圍之內),但請嘗試將所有內容轉換爲UTF-8:'Test $ Player < - iconv(Test $ Player,to ='UTF-8')''。查看索引是否按預期工作。如果您不強制編碼,字符串將根據您的系統區域設置進行解釋(您提供的示例在我的系統上按預期工作)。 – ilir

回答

3

編輯:看起來你提供的文件使用的編碼不同於你係統的原生編碼。

的(實驗)編碼由stri_enc_detect函數從stringi包進行檢測,給出:

library('stringi') 
PlayerDataRaw <- stri_read_raw('~/Desktop/PLAYERS.csv') 
stri_enc_detect(PlayerDataRaw) 
## [[1]] 
## [[1]]$Encoding 
## [1] "ISO-8859-1" "ISO-8859-2" "ISO-8859-9" "IBM424_rtl" 
## 
## [[1]]$Language 
## [1] "en" "ro" "tr" "he" 
## 
## [[1]]$Confidence 
## [1] 0.25 0.14 0.09 0.02 

因此最有可能該文件是在ISO-8859-1亦稱latin1。幸運的是,R在讀取此文件時不必重新編碼輸入 - 它可能只設置與默認(== native)編碼標記不同的值。您可以使用以下文件加載文件:

PlayerData<-read.table('~/Desktop/PLAYERS.csv', 
    quote=NULL, dec = ".", sep=",", 
    stringsAsFactors=FALSE, header=TRUE, fill=TRUE, 
    blank.lines.skip=TRUE, encoding='latin1') 

現在您可以正確訪問單個字符,例如與stri_sub功能:

Test<-PlayerData[c(33655:33656),] 
Test 
##   T   Away H.A Home Player Year 
## 33655 33654 CrystalPalace 1 Arsenal Cazorla 2013 
## 33656 33655 CrystalPalace 1 Arsenal Özil 2013 

stri_sub(Test$Player, 1, length=1) 
## [1] "C" "Ö" 
stri_sub(Test$Player, 2, length=1) 
## [1] "a" "z" 

按照比較字符串,這裏的結果對於字符串平等的測試,用重音字符「扁平化」:

stri_cmp_eq("Özil", "Ozil", stri_opts_collator(strength=1)) 
## [1] TRUE 

你也可以改掉口音通過使用iconv的音譯器(我不確定它是否在Windows上可用)。

iconv(Test$Player, 'latin1', 'ASCII//TRANSLIT') 
## [1] "Cazorla" "Ozil" 

或者從stringi包(stringi版本> = 0.2-2)一個非常強大的transliterator:

stri_trans_general(Test$Player, 'Latin-ASCII') 
## [1] "Cazorla" "Ozil" 
+0

偉大的答案 - 'iconv'的音譯器函數非常有效地對此進行排序。 – Pash101

0

謝謝大家對這個您的幫助。

這些字符串已被正確編碼爲UTF-8(我向read.table以及使用iconv添加了參數,如所建議的那樣)。這似乎不是問題。

我也使用stri_sub()函數。但是這似乎也不起作用(它也將該口音作爲單獨的字符stri_sub("Özil",1,3) = "Ã<U+0096>z"處理)。

但是,感謝你指着我的stringi文檔的方向,它給了我,我很樂意用一種變通方法的理念是:

remove.accents<-function(s){ 
oldrefs<-c(214,225)#Ö, á 
newrefs<-c(79,97)#O,a 

New<-utf8ToInt(s) 
for(i in 1:length(oldrefs)){ 
New<-as.numeric(gsub(oldrefs[i],newrefs[i],New)) 
NEW<-intToUtf8(New) 
} 
NEW 
} 
> (remove.accents("Özil")) 
[1] "Ozil" 
> (remove.accents("Suárez")) 
[1] "Suarez" 

我現在可以填充oldrefs/newref陣列對於某些球員(TouréJääskeläinen,Agüero等)我需要其他角色的Int參考,希望這些參賽者不會花太長時間!

+0

感謝您指出了這個有趣的字符串處理任務,我很快就開始着手將自動音譯機制包括到stringi中,參見[this issue](https://github.com/Rexamine/stringi/issues/72) – gagolews

+0

如果' stri_sub'沒有正常工作,我相信你的數據沒有被正確讀取。調用'Encoding(Test $ Player)'的結果是什麼? – gagolews

+0

我已經在導入之前將'encoding ='UTF-8''參數包含到'read.table'中。 '編碼(測試$播放器)'現在給了我這個輸出:'「未知」「UTF-8」'(在這種情況下未知的是卡索拉; UTF-8,第二個播放器是厄齊爾)。另外,通過UTF-8參數,意味着Özil現在顯示爲' zil' – Pash101