2014-04-18 18 views
6

Tôi có một cơ sở dữ liệu chứa tên của các cầu thủ Premiership mà tôi đang đọc vào R (3.02), nhưng tôi gặp phải những khó khăn khi nói đến người chơi có nhân vật nước ngoài trong tên của họ (dấu, dấu trọng âm, vv). Đoạn mã dưới đây minh họa điều này:Đọc các ký tự nước ngoài

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 

Tôi đã cố gắng thay thế các nhân vật, như mô tả ở đây: R: Replacing foreign characters in a string, nhưng như các ký tự có dấu trong ví dụ của tôi xuất hiện để được đọc như hai nhân vật riêng biệt Tôi không nghĩ rằng nó hoạt động.

Tôi sẽ biết ơn vì bất kỳ đề xuất hoặc cách giải quyết nào.

Tệp có sẵn để tải xuống here.

+0

Bạn có thể đặt hai dòng CSV của mình ở đâu đó trên mạng không? Có thể 'iconv' có thể giúp bạn. –

+1

Điều này đòi hỏi một câu trả lời dài hơn nhiều (hầu hết là ngoài chuyên môn của tôi), nhưng hãy thử chuyển đổi mọi thứ thành UTF-8: 'Test $ Player <- iconv (Test $ Player, to = 'UTF-8')'. Xem liệu việc lập chỉ mục có hoạt động như mong đợi hay không. Nếu bạn không ép buộc mã hóa, các chuỗi ký tự sẽ được diễn giải tùy thuộc vào ngôn ngữ hệ thống của bạn (các ví dụ bạn cung cấp đã làm việc như mong đợi trên hệ thống của tôi). – ilir

Trả lời

3

EDIT: Dường như tệp bạn đã cung cấp sử dụng mã hóa khác với mã gốc của hệ thống.

An (thử nghiệm) phát hiện mã hóa được thực hiện bởi stri_enc_detect chức năng từ gói stringi cho:

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 

Vì vậy, nhiều khả năng các tập tin là trong ISO-8859-1 a.k.a. latin1. May mắn thay, R không phải mã hóa lại đầu vào trong khi đọc tệp này - nó chỉ có thể đặt khác với đánh dấu mã hóa mặc định (== gốc). Bạn có thể tải tệp bằng:

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

Bây giờ bạn có thể truy cập các ký tự riêng lẻ một cách chính xác, ví dụ: với stri_sub chức năng:

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" 

Theo so sánh chuỗi, sau đây là các kết quả cho một thử nghiệm cho sự bình đẳng của chuỗi, với các nhân vật giọng "san phẳng":

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

Bạn cũng có thể thoát khỏi giọng ký tự bằng cách sử dụng phiên dịch viên của iconv (Tôi không chắc chắn liệu nó có sẵn trên Windows hay không).

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

Hoặc với một transliterator rất mạnh mẽ từ stringi gói (stringi phiên bản> = 0,2-2):

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

Câu trả lời hay - chức năng phiên âm của 'iconv' hoạt động rất tốt để sắp xếp điều này. – Pash101

0

Cảm ơn tất cả các bạn đã giúp đỡ của bạn với điều này.

Các chuỗi đã được mã hóa đúng UTF-8 (tôi đã thêm đối số vào read.table cũng như sử dụng iconv, như được đề xuất). Điều này dường như không phải là vấn đề.

Tôi cũng đã sử dụng chức năng stri_sub(). nhưng điều này cũng có vẻ không hoạt động (nó cũng coi trọng âm là một ký tự riêng biệt stri_sub("Özil",1,3) = "Ã<U+0096>z").

Tuy nhiên, cảm ơn bạn đã chỉ cho tôi trong sự chỉ đạo của các tài liệu stringi, nó đã cho tôi ý tưởng cho một workaround mà tôi rất hạnh phúc khi sử dụng:

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" 

tôi bây giờ có thể cư trú trong oldrefs/newref mảng với các tài liệu tham khảo Int cho các nhân vật khác tôi sẽ cần cho một số cầu thủ (Touré Jääskeläinen, Agüero, vv) mà hy vọng không nên mất quá nhiều thời gian!

+0

Cảm ơn bạn đã chỉ ra nhiệm vụ xử lý chuỗi thú vị này, tôi sẽ sớm bắt đầu làm việc bao gồm các cơ chế chuyển tự động thành stringi, xem [vấn đề này] (https://github.com/Rexamine/stringi/issues/72) – gagolews

+0

Nếu ' stri_sub' không hoạt động chính xác, tôi chắc chắn dữ liệu của bạn chưa được đọc chính xác. Kết quả của việc gọi 'Encoding (Test $ Player)' là gì? – gagolews

+0

Tôi đã đưa đối số 'encoding = 'UTF-8'' vào' read.table' trước khi nhập. 'Encoding (Test $ Player)' bây giờ cho tôi kết quả này: '" unknown "" UTF-8 "' (không rõ trong trường hợp này là Cazorla; UTF-8, trình phát thứ hai, là Özil). Ngoài ra, chuyển đối số UTF-8, có nghĩa là Özil bây giờ xuất hiện dưới dạng ' zil' – Pash101

Các vấn đề liên quan