
Desde hace unos meses estoy trabajando con datos de exportaciones de productos por países. Básicamente se trata de un análisis comparativo sobre cómo han evolucionado algunos estados cambiando su cartera exportadora hacia bienes que requieren más valor añadido, frente a otros países que no han realizado dichos cambios. La idea, resumida, se puede encontrar en este artículo que apareció en el blog Nada es Gratis.
No quiero hablar de los resultados, sino de las trampas de los datos y de lo fácil que es procesarlos con R. La base de datos de partida la facilita Naciones Unidas a través de COMTRADE. En este caso, los datos brutos son las exportaciones por productos de cada país al resto del mundo en distintos años (1 800 000 registros aproximadamente). Los productos aparecen con una clasificación lexicográfica que llega a los 5 dígitos (llamada SITC revisión 3) y cuanto menos dígitos, mayor nivel de agregación. Por ejemplo, el código 3 son los combustibles y lubricantes de origen mineral, el 33 el petróleo y sus derivados, el 334 los productos derivados del petróleo y así hasta 5 dígitos de desagregación.
Pensé que para extraer los datos que necesitaba al máximo nivel de desagregación (el producto) bastaba, ingenuo de mi, con seleccionar aquellos registros con un código de 5 dígitos, el nivel más desagregado. Sin embargo, los hados de los datos no aprecian el trabajo fácil de los mortales y les gusta ponernos a prueba. Resulta que para algunos grupos de bienes no aparece desagregación hasta los 5 dígitos y el máximo nivel de detalle son cuatro o puede que tres. Adjunto unas filas de la lista de productos para ilustrar el problema, donde se aprecia que el petróleo crudo aparece con cuatro dígitos, mientras que otros productos derivados lo hacen con cinco:
| comm.code | comm.desc |
|---|---|
| 3 | Mineral fuels, lubricants and related materials |
| 33 | PETROLEUM,PETROL.PRODUCT |
| 333 | PETROLEUM OILS, CRUDE |
| 3330 | Crude petroleum |
| 334 | PETROLEUM PRODUCTS |
| 3341 | Motor gasolene,light oil |
| 33411 | Motor spirit (gasoline), including aviation spirit |
| 33412 | Spirit-type (gasoline-type) jet fuel |
| 33419 | Other light petroleum oils and light oils obtained from bituminous minera |
El objetivo, partiendo del conjunto de todos los códigos, consiste en retener aquellos correspondientes a productos, es decir, que no aparezcan desagregados a un nivel inferior (lo que indicaría un grupo), con independencia del número de dígitos del código. Así, empezando por las 10 agrupaciones de un dígito, lo que quiero es comprobar si cada una está desagregada en códigos de más dígitos, si lo está, borro el registro con menos dígitos, pero si no, lo tengo que conservar porque es la máxima desagregación disponible para ese conjunto de bienes. Una vez eliminadas las filas de un dígito, se procesan las de 2 y así hasta llegar a los códigos de 4 dígitos.
Mi solución, que empezando con todos los códigos en uccode deja aquellos más desagregados es:
prodlist < - read.csv("http://www.grserrano.es/datos/prodlist.csv", colClasses="character") uccode <- prodlist$comm.code for (ndigits in c(1:4)) { test1 <- uccode[nchar(uccode)==ndigits] for (dd in test1) { nsub <- grep(paste("^", dd, sep=""), uccode) if (length(nsub)>1) uccode < - uccode[-match(dd, uccode)] } } prodlist.1 <- subset(prodlist, comm.code %in% uccode) |
El archivo con los códigos (comm.code) y descripciones (comm.desc) de los 4193 grupos/productos se puede descargar aquí. ¿A alguien se le ocurre una forma de hacerlo en menos líneas y/o más legible (con R)?
Tirando de expresiones regulares:
uccode.0 <- uccode <- prodlist$comm.codemi.filtro <- function( x )
all( ! grepl( paste( "^", x, ".+", sep = "" ), uccode.0 ) )
res <- Filter( mi.filtro, uccode )
Pues sí, exactamente el mismo resultado. Gracias.