У меня есть этот файл (http://b7hq6v.alterupload.com/en/), который я хочу прочитать в R с помощью read.csv
. Но я не могу определить правильную кодировку. Кажется, это что-то вроде UTF-8. Я использую R 2.12.1 на компьютере с WindowsXP. Любая помощь?
Как определить правильную кодировку для read.csv?
Ответы (6)
Прежде всего на основе более общего вопроса о StackOverflow невозможно определить кодировку файла со 100% уверенностью.
Я много раз боролся с этим и пришел к неавтоматическому решению:
Используйте iconvlist
, чтобы получить все возможные кодировки:
codepages <- setNames(iconvlist(), iconvlist())
Затем прочитайте данные, используя каждый из них
x <- lapply(codepages, function(enc) try(read.table("encoding.asc",
fileEncoding=enc,
nrows=3, header=TRUE, sep="\t"))) # you get lots of errors/warning here
Здесь важно знать структуру файла (разделитель, заголовки). Установите кодировку, используя аргумент fileEncoding
. Прочитано только несколько строк.
Теперь вы можете искать результаты:
unique(do.call(rbind, sapply(x, dim)))
# [,1] [,2]
# 437 14 2
# CP1200 3 29
# CP12000 0 1
Похоже, правильный вариант с 3 строками и 29 столбцами, так что давайте посмотрим на них:
maybe_ok <- sapply(x, function(x) isTRUE(all.equal(dim(x), c(3,29))))
codepages[maybe_ok]
# CP1200 UCS-2LE UTF-16 UTF-16LE UTF16 UTF16LE
# "CP1200" "UCS-2LE" "UTF-16" "UTF-16LE" "UTF16" "UTF16LE"
Вы также можете посмотреть данные
x[maybe_ok]
Для вашего файла все эти кодировки возвращают идентичные данные (частично из-за некоторой избыточности, как вы видите).
Если вы не знаете специфику своего файла, вам нужно использовать readLines
с некоторыми изменениями в рабочем процессе (например, вы не можете использовать fileEncoding
, должны использовать length
вместо dim
, сделайте больше магии, чтобы найти правильные).
iconv
.
- person hadley; 22.11.2012
read.csv
не связана с fileEncoding
.
- person Tunn; 24.11.2016
Пакет readr
, https://cran.r-project.org/web/packages/readr/readr.pdf включает функцию guess_encoding
, которая вычисляет вероятность того, что файл будет закодирован в нескольких кодировках:
guess_encoding("your_file", n_max = 1000)
guess_encoding
не дает определенных результатов. Пробовал на 11 CSV-файлах, и 2 из них были поровну разделены между несколькими кодировками.
- person Dutschke; 13.08.2020
Во-первых, надо разобраться, что такое кодировка файла, что нельзя сделать в R (по крайней мере, насколько я знаю). Вы можете использовать для этого внешние инструменты, например. из Perl, Python или, например. утилита file
под Linux/UNIX.
Как предложил @ssmit, у вас здесь кодировка UTF-16LE (Unicode), поэтому загрузите файл с этой кодировкой и используйте readLines
, чтобы увидеть, что у вас есть в первых (например) 10 строках:
> f <- file('encoding.asc', open="r", encoding="UTF-16LE") # UTF-16LE, which is "called" Unicode in Windows
> readLines(f,10)
[1] "\tFe 2\tZn\tO\tC\tSi\tMn\tP\tS\tAl\tN\tCr\tNi\tMo\tCu\tV\tNb 2\tTi\tB\tZr\tCa\tH\tCo\tMg\tPb 2\tW\tCl\tNa 3\tAr"
[2] ""
[3] "0\t0,003128\t3,82E-05\t0,0004196\t0\t0,001869\t0,005836\t0,004463\t0,002861\t0,02148\t0\t0,004768\t0,0003052\t0\t0,0037\t0,0391\t0,06409\t0,1157\t0,004654\t0\t0\t0\t0,00824\t7,63E-05\t0,003891\t0,004501\t0\t0,001335\t0,01175"
[4] "0,0005\t0,003265\t3,05E-05\t0,0003662\t0\t0,001709\t0,005798\t0,004395\t0,002808\t0,02155\t0\t0,004578\t0,0002441\t0\t0,003601\t0,03897\t0,06406\t0,1158\t0,0047\t0\t0\t0\t0,008026\t6,10E-05\t0,003876\t0,004425\t0\t0,001343\t0,01157"
[5] "0,001\t0,003332\t2,54E-05\t0,0003052\t0\t0,001704\t0,005671\t0,0044\t0,002823\t0,02164\t0\t0,004603\t0,0003306\t0\t0,003611\t0,03886\t0,06406\t0,1159\t0,004705\t0\t0\t0\t0,008036\t5,09E-05\t0,003815\t0,004501\t0\t0,001246\t0,01155"
[6] "0,0015\t0,003313\t2,18E-05\t0,0002616\t0\t0,001678\t0,005689\t0,004447\t0,002921\t0,02171\t0\t0,004621\t0,0003488\t0\t0,003597\t0,03889\t0,06404\t0,1158\t0,004752\t0\t0\t0\t0,008022\t4,36E-05\t0,003815\t0,004578\t0\t0,001264\t0,01144"
[7] "0,002\t0,003313\t2,18E-05\t0,0002834\t0\t0,001591\t0,005646\t0,00436\t0,003008\t0,0218\t0\t0,004643\t0,0003488\t0\t0,003619\t0,03895\t0,06383\t0,1159\t0,004752\t0\t0\t0\t0,008\t4,36E-05\t0,003771\t0,004643\t0\t0,001351\t0,01142"
[8] "0,0025\t0,003488\t2,18E-05\t0,000218\t0\t0,001657\t0,00558\t0,004338\t0,002986\t0,02175\t0\t0,004469\t0,0002616\t0\t0,00351\t0,03889\t0,06374\t0,1159\t0,004621\t0\t0\t0\t0,008131\t4,36E-05\t0,003771\t0,004708\t0\t0,001243\t0,01125"
[9] "0,003\t0,003619\t0\t0,0001526\t0\t0,001591\t0,005668\t0,004207\t0,00303\t0,02169\t0\t0,00449\t0,0002834\t0\t0,00351\t0,03874\t0,06383\t0,116\t0,004665\t0\t0\t0\t0,007956\t0\t0,003749\t0,004796\t0\t0,001286\t0,01125"
[10] "0,0035\t0,003422\t0\t4,36E-05\t0\t0,001482\t0,005711\t0,004185\t0,003292\t0,02156\t0\t0,004665\t0,0003488\t0\t0,003553\t0,03852\t0,06391\t0,1158\t0,004708\t0\t0\t0\t0,007717\t0\t0,003597\t0,004905\t0\t0,00133\t0,01136"
Отсюда видно, что у нас есть заголовок, а во второй строке пустая строка (которая по умолчанию будет пропущена с помощью функции read.table
), разделитель \t
и десятичный символ ,
.
> f <- file('encoding.asc', open="r", encoding="UTF-16LE")
> df <- read.table(f, sep='\t', dec=',', header=TRUE)
И посмотрим, что у нас есть:
> head(df)
X Fe.2 Zn O C Si Mn P S
1 0.0000 0.003128 3.82e-05 0.0004196 0 0.001869 0.005836 0.004463 0.002861
2 0.0005 0.003265 3.05e-05 0.0003662 0 0.001709 0.005798 0.004395 0.002808
3 0.0010 0.003332 2.54e-05 0.0003052 0 0.001704 0.005671 0.004400 0.002823
4 0.0015 0.003313 2.18e-05 0.0002616 0 0.001678 0.005689 0.004447 0.002921
5 0.0020 0.003313 2.18e-05 0.0002834 0 0.001591 0.005646 0.004360 0.003008
6 0.0025 0.003488 2.18e-05 0.0002180 0 0.001657 0.005580 0.004338 0.002986
Al N Cr Ni Mo Cu V Nb.2 Ti B Zr
1 0.02148 0 0.004768 0.0003052 0 0.003700 0.03910 0.06409 0.1157 0.004654 0
2 0.02155 0 0.004578 0.0002441 0 0.003601 0.03897 0.06406 0.1158 0.004700 0
3 0.02164 0 0.004603 0.0003306 0 0.003611 0.03886 0.06406 0.1159 0.004705 0
4 0.02171 0 0.004621 0.0003488 0 0.003597 0.03889 0.06404 0.1158 0.004752 0
5 0.02180 0 0.004643 0.0003488 0 0.003619 0.03895 0.06383 0.1159 0.004752 0
6 0.02175 0 0.004469 0.0002616 0 0.003510 0.03889 0.06374 0.1159 0.004621 0
Ca H Co Mg Pb.2 W Cl Na.3 Ar
1 0 0 0.008240 7.63e-05 0.003891 0.004501 0 0.001335 0.01175
2 0 0 0.008026 6.10e-05 0.003876 0.004425 0 0.001343 0.01157
3 0 0 0.008036 5.09e-05 0.003815 0.004501 0 0.001246 0.01155
4 0 0 0.008022 4.36e-05 0.003815 0.004578 0 0.001264 0.01144
5 0 0 0.008000 4.36e-05 0.003771 0.004643 0 0.001351 0.01142
6 0 0 0.008131 4.36e-05 0.003771 0.004708 0 0.001243 0.01125
skip=2
можно опустить (я отредактировал свой ответ на основе этого), вторая пустая строка будет пропущена. Вы также можете использовать функцию read.csv
для чтения этого файла (с теми же заданными параметрами), но, поскольку ваш файл разделен не запятыми, а табуляторами, я не думаю, что это было бы красиво. Ищите ?read.table
для получения подробной информации о сходстве функций (различия можно найти в значениях по умолчанию).
- person daroczig; 27.01.2011
Помимо использования пакета readr, вы также можете использовать stringi::stri_enc_detect2. Эта функция особенно эффективна, если известна локаль и если вы имеете дело с какой-либо формой UTF или ASCII: «... оказывается, что (эмпирически) stri_enc_detect2 работает лучше, чем на основе ICU [ stringi::stri_enc_detect используется guess_encoding], если предоставлен текст UTF-*."
Подробнее о stringi::stri_enc_detect.
Подробнее о stringi::stri_enc_detect2.
Запрос на изменение для предположения_кодирования
Этот файл имеет кодировку UTF-16LE со спецификацией (знак порядка байтов). Вероятно, вам следует использовать encoding = "UTF-16LE"
read.table
правильным параметром является fileEncoding
.
- person Marek; 27.01.2011
Мое аккуратное обновление решения @marek, так как я столкнулся с той же проблемой в 2020 году:
#Libraries
library(magrittr)
library(purrr)
#Make a vector of all the encodings supported by R
encodings <- set_names(iconvlist(), iconvlist())
#Make a simple reader function
reader <- function(encoding, file) {
read.csv(file, fileEncoding = encoding, nrows = 3, header = TRUE)
}
#Create a "safe" version so we only get warnings, but errors don't stop it
# (May not always be necessary)
safe_reader <- safely(reader)
#Use the safe function with the encodings and the file being interrogated
map(encodings, safe_reader, `<TEST FILE LOCATION GOES HERE>`) %>%
#Return just the results
map("result") %>%
#Keep only results that are dataframes
keep(is.data.frame) %>%
#Keep only results with more than one column
#This predicate will need to change with the data
#I knew this would work, because I could open in a text editor
keep(~ ncol(.x) > 1) %>%
#Return the names of the encodings
names()