¿Cómo detectar la encoding correcta para read.csv?

Tengo este archivo (http://b7hq6v.alterupload.com/en/) que quiero leer en R con read.csv . Pero no puedo detectar la encoding correcta. Parece ser una especie de UTF-8. Estoy usando R 2.12.1 en una máquina con Windows XP. ¿Alguna ayuda?

    En primer lugar, basado en una pregunta más general sobre StackOverflow, no es posible detectar la encoding del archivo con una certeza del 100%.

    He luchado esto muchas veces y he llegado a una solución no automática:

    Use iconvlist para obtener todas las codificaciones posibles:

     codepages < - setNames(iconvlist(), iconvlist()) 

    Luego lea los datos usando cada uno de ellos

     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 

    Importante aquí es conocer la estructura del archivo (separador, encabezados). Establecer la encoding utilizando el argumento fileEncoding . Lea solo algunas filas.
    Ahora puedes buscar resultados:

     unique(do.call(rbind, sapply(x, dim))) # [,1] [,2] # 437 14 2 # CP1200 3 29 # CP12000 0 1 

    Parece que la correcta es aquella con 3 filas y 29 columnas, así que vamos a verlas:

     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" 

    Podrías mirar los datos también

     x[maybe_ok] 

    Para su archivo, todas estas codificaciones devuelven datos idénticos (en parte porque hay cierta redundancia, como puede ver).

    Si no conoce su archivo en particular, necesita usar readLines con algunos cambios en el flujo de trabajo (por ejemplo, no puede usar fileEncoding , debe usar length lugar de dim , hacer más magic para encontrar los correctos).

    El paquete readr , https://cran.r-project.org/web/packages/readr/readr.pdf , incluye una función llamada guess_encoding que calcula la probabilidad de que un archivo se codifique en varias codificaciones:

     guess_encoding("your_file", n_max = 1000) 

    Primero, debes averiguar cuál es la encoding del archivo, qué no se puede hacer en R (al menos como sé). Puede usar herramientas externas para ello, por ejemplo, de Perl, Python o, por ejemplo. la utilidad de file en Linux / UNIX.

    Como sugirió @ssmit, aquí tiene una encoding UTF-16LE (Unicode), así que cargue el archivo con esta encoding y use readLines para ver lo que tiene en la primera (por ejemplo) 10 líneas:

     > 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" 

    A partir de esto, se puede ver que tenemos un encabezado y una línea en blanco en la segunda fila (que se saltará de manera predeterminada con la función read.table ), el separador es \t y el carácter decimal es read.table

     > f < - file('encoding.asc', open="r", encoding="UTF-16LE") > df < - read.table(f, sep='\t', dec=',', header=TRUE) 

    Y mira lo que tenemos:

     > head(df) X Fe.2 Zn OC Si Mn PS 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 

    Además de usar el paquete de lectura , también puede optar por utilizar stringi :: stri_enc_detect2 . Esta función es particularmente eficiente si se conoce la configuración regional y si se trata de alguna forma de UTF o ASCII: “… resulta que (empíricamente) stri_enc_detect2 funciona mejor que la basada en la ICU [ stringi :: stri_enc_detect utilizada por el guess_encoding ] si se proporciona texto UTF- *.

    Detalles sobre stringi :: stri_enc_detect .

    Detalles sobre stringi :: stri_enc_detect2 .

    Solicitud de cambio para guess_encoding

    Este archivo tiene encoding UTF-16LE con BOM (marca de orden de bytes). Probablemente deberías usar encoding = "UTF-16LE"