OpenRefine ofrece la posibilidad de consultar fuentes externas, una función que es muy útil cuando se intenta mejorar la calidad de los datos. Para el caso particular de datos sobre biodiversidad, permite, por ejemplo, validar nombres taxonómicos y geográficos contra fuentes de información que se consideren confiables, completar rangos taxonómicos y campos de geografía administrativa, georreferenciar, incorporar enlaces a imágenes almacenadas en sitios web, entre otros.
En OpenRefine las consultas externas pueden realizarse por dos vías: a través de URLs, o a través de servicios de reconciliación. En esta guía sólo se incluyen los métodos referidos a las consultas a través de URLs. Para ver explicaciones referidas al uso de algunos servicios de reconciliación consultar versiones anteriores de este documento; tener en cuenta que esos servicios no han sido actualizados en concordancia con las actualizaciones de OpenRefine, y muchos no funcionan a partir de la versión 2.8 de OpenRefine.
Note
|
Debe recordarse que para poder realizar consultas a servicios que se encuentran en línea se requiere conexión a Internet. |
Note
|
La velocidad a la que se obtienen los resultados de las consultas depende de la velocidad de respuesta del servicio en particular. De esta forma, si se quiere obtener información para muchos registros, el tiempo de la operación será prolongado. Para acortar tiempos, se pueden hacer comparaciones de registros contra el servicio deseado dentro de facetas, es decir, en fracciones particulares de los registros. |
Nos referimos a consultas a través de URLs cuando el proceso implica proveer a OpenRefine con la dirección web (URL) de un determinado servicio y ciertos parámetros mínimos para obtener de dicho servicio un resultado.
En el ejemplo siguiente, compararemos los nombres científicos (contenidos en el campo "scientificName"
) contra el servicio Global Names Resolver (de aquí en más "GNR").
Para acortar el tiempo de consulta, cree una faceta para el campo "genus"
(click en "la ▼ azul > Facetas > Faceta de texto") y dentro de ella escoja el género Cinna. En el conjunto de datos utilizado Cinna tiene 3 especies asociadas: C. lateralis (1 registro), C. arundinacea (6 registros) y C. latifolia (3 registros); puede verlas listadas en el campo "scientificName"
.
Para comparar los nombres contra el GNR, haremos un llamado al servicio y capturaremos los resultados en un nuevo campo:
A partir del campo "scientificName"
, cree una nueva columna a partir de una dirección URL haciendo click en menu:la ▼ azul del campo[] y siguiendo la siguiente ruta (Figura 47):
"Editar columnas > Agregar columna accediendo a URLs…"
Se abrirá una ventana como la mostrada en la Figura 48. Allí, dé un nombre al nuevo campo (por ejemplo, GNR_Json_sciName), y en el cuadro de texto coloque la siguiente expresión:
"http://resolver.globalnames.org/name_resolvers.json?names=" +
escape(cells["scientificName"].value,"url")
Dicha expresión indica que se hará una consulta en el GNR utilizando como valores de comparación aquellos que se encuentran en el campo "scientificName"
. Es importante que el nombre del campo que utiliza en la expresión sea idéntico al nombre del campo del cual tomará los valores originales, o de otro modo el llamado será infructuoso.
Note que en esta ventana, arriba a la derecha, tiene una opción para modificar el “Tiempo de retraso”. Este valor indica el tiempo que transcurre entre llamados o consultas sucesivas que se hacen al servicio en cuestión. Por defecto, el valor es de 5000 milisegundos. Puede reducir este tiempo para acelerar el proceso de comparación. Tenga en cuenta, sin embargo, que muchos servicios bloquean los llamados si éstos ocurren muy cercanos en el tiempo, pues consideran que puede tratarse de un ataque. El máximo número de consultas que se pueden realizar por unidad de tiempo depende de cada servicio en particular.
Note
|
La expresión utilizada es muy general, y devolverá los valores de todos los parámetros que GNR provee respecto de un nombre científico. Puede consultar dichos parámetros en http://resolver.globalnames.org/api. Si no quiere obtener en el resultado todos los valores, puede modificar la expresión especificando valores para todos o algunos de los parámetros. Por ejemplo: GNR resuelve los nombres consultando diferentes fuentes, a las que asigna identificadores (data_source_id); si sólo quiere obtener los resultados provenientes de la fuente Catalogue of Life (que en GNR tiene id=1), puede utilizar la siguiente expresión: |
"http://resolver.globalnames.org/name_resolvers.json?names=" +
escape(cells["scientificName"].value,"url") +
"&data_source_ids=1"
Una vez que haya creado el nuevo campo con la expresión general, verá que contiene, en formato JSON, los resultados de la consulta en GNR para cada nombre, con todos los parámetros y valores que GNR reporta.
Para poder trabajar con esto más cómodamente, debemos extraer de allí los valores de interés.
Dado que GNR consulta varias fuentes de nombres taxonómicos, nos interesa saber cuál es el nombre científico que figura en cada fuente. Algunas fuentes pueden tener listado el nombre pero considerarlo inválido y proveer el nombre correcto. Entonces, extraeremos del resultado en JSON, en un nuevo campo, los siguientes valores:
-
Fuente consultada: "data_source_title"
-
Nombre encontrado en la fuente: "name_string"
-
Nombre aceptado por la fuente: "current_name_string"
Para ello, a partir del campo en JSON (en el ejemplo, GNR_Json_sciName), cree un nuevo campo (haga click en "la ▼ azul > Editar columnas > Agregar columna basada en esta columna").
Dé un nombre al nuevo campo (por ejemplo, GNR_sciName_options) y en el cuadro de texto, coloque la siguiente expresión (Figura 49):
forEach(value.parseJson().get("data")[0].get("results"), v,
v.get("data_source_title") + "; " +
v.get("name_string") + "; " +
if(isBlank(v.get("current_name_string")), "", v.get("current_name_string")))
.join(" | ")
Dicha expresión analiza la cadena en formato JSON, que tiene dentro de su estructura secciones “data” y dentro de esta “results” –un “result” proveniente de cada fuente consultada (por ejemplo, un “result” de Catalogue of Life). Dentro de cada sección “results” extrae los valores de interés (“data_source_title”, “name_string” y “current_name_string”) y los separa con un “;”. Como no todas las fuentes proveen un nombre aceptado (“current_name_string”), la expresión if
especifica que si ese parámetro es nulo debe dejarse el espacio vacío (""
), y si no, colocar el valor extraído. Por último, une los grupos de valores extraídos en una única cadena de texto, separados por un |
.
Una vez que haya creado el campo, verá que contiene los valores de interés extraídos de GNR separados por ' | '. Por ejemplo:
uBio NameBank; Cinna lateralis; | Catalogue of Life; Cinna lateralis Walter; Andropogon virginicus L. | ITIS; Cinna lateralis Walter; Andropogon virginicus L. | GBIF Backbone Taxonomy; Cinna lateralis Walter; Andropogon virginicus L. | EOL; Cinna lateralis Walter; | Tropicos - Missouri Botanical Garden; Cinna lateralis Walter; | The International Plant Names Index; Cinna lateralis Walter; | uBio NameBank; Cinna lateralis Walter; | uBio NameBank; Cinna lateralis Walter, 1788; | Arctos; Cinna lateralis Walter;
Note que algunas fuentes encuentran el nombre pero no proveen un nombre aceptado, por ejemplo:
uBio NameBank; Cinna lateralis;
no tiene un valor en el tercer lugar, mientras que:
Catalogue of Life; Cinna lateralis Walter; Andropogon virginicus L.
provee el nombre encontrado y el nombre válido.
Note además que algunas fuentes tienen más de una variante asociada al nombre, por ejemplo:
uBio NameBank; Cinna lateralis;
uBio NameBank; Cinna lateralis Walter;
uBio NameBank; Cinna lateralis Walter, 1788;
Important
|
No todos los nombres serán necesariamente encontrados en todas las fuentes consultadas, por lo que el número de fuentes variará de un nombre al otro. En consecuencia, la ubicación de las fuentes en la cadena de texto no será homogénea de un registro al otro. Una consecuencia de esto es que si usted quiere luego separar el contenido en campos distintos de acuerdo a la fuente consultada (e.g., un campo para ITIS, uno para Catalogue of Life, etc.), no podrá hacerlo de modo que cada nuevo campo tenga los datos de una misma y única fuente. |
En este caso, le conviene en cambio hacer varios llamados a GNR separados, cada uno especificando una fuente determinada. Como se menciona más arriba, si quiere por ejemplo sólo consultar los valores dados por Catalogue of Life, use la expresión siguiente:
"http://resolver.globalnames.org/name_resolvers.json?names=" +
escape(cells["scientificName"].value,"url") +
"&data_source_ids=1"
y luego arme un nuevo campo extrayendo los resultados de interés, usando la expresión:
forEach(value.parseJson().get("data")[0].get("results"), v,
v.get("data_source_title") + "; " +
v.get("name_string") + "; " +
if(isBlank(v.get("current_name_string")), "", v.get("current_name_string")))
.join(" | ")
A partir de los resultados obtenidos, puede extraer los nombres separando la nueva columna en columnas distintas utilizando separadores apropiados (ver Divisiones en la sección 2.1.3).
En este ejemplo, para facilitar la explicación y reducir el tiempo de consulta al servicio, construiremos previamente dos facetas. La primera sobre el campo "country"
, dentro de la cual seleccionaremos el valor “Argentina”. La segunda faceta será sobre el campo "genus"
, dentro de la cual seleccionaremos el valor “Acacia”. Una vez aplicadas ambas facetas y escogidos los valores, verá que en la ventana principal sólo se muestra un subconjunto de registros que cumplen estas condiciones simultáneamente.
Llevaremos a cabo la georreferenciación a partir del campo "locality"
. Para ello, cree un nuevo campo a partir de éste siguiendo la ruta: click en "la ▼ azul > Editar columnas > Agregar columna accediendo a URLs…".
Se abrirá una nueva ventana (Figura 50). Allí dé un nombre al nuevo campo, por ejemplo “GeoLocate_Json_georref”, y pegue en el cuadro de texto la siguiente expresión:
"http://www.geo-locate.org/webservices/geolocatesvcv2/glcwrap.aspx?Country=Argentina&fmt=json&Locality=" +
escape(value,'url')
En esta expresión, fmt
indica el formato en el que el resultado será devuelto por el servicio. GEOLocate ofrece dos posibles formatos, JSON y GeoJSON.
Una vez que haya creado el nuevo campo con la expresión general, verá que contiene, en formato JSON, los resultados de la consulta en GEOLocate para cada localidad, con todos los parámetros y valores que este servicio reporta.
En los resultados puede tener tres casos:
Caso 1) Ningún resultado encontrado. Ello quiere decir que GEOLocate no ha podido ubicar la localidad de interés. En la celda correspondiente verá lo siguiente:
{
"engineVersion" : "GLC:7.0|U:1.01374|eng:1.0",
"numResults" : 0, (1)
"executionTimems" : 578.1462
}
-
Ningún resultado encontrado.
Caso 2) Un único resultado encontrado. En la celda correspondiente verá, por ejemplo, lo siguiente:
{
"engineVersion": "GLC:7.0|U:1.01374|eng:1.0",
"numResults": 1,
"executionTimems": 484.3969,
"resultSet": {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [ -64.471941, -23.643418 ] (1)
},
"properties": {
"parsePattern": "YUTO", (2)
"precision": "High",
"score": 79,
"uncertaintyRadiusMeters": 3036, (3)
"uncertaintyPolygon": "Unavailable", (4)
"displacedDistanceMiles": 0, (5)
"displacedHeadingDegrees": 0,
"debug": ":GazPartMatch=False|:inAdm=True|:Adm=JUJUY|:NPExtent=5040|:NP=YUTO|:KFID=|YUTO" (6)
}
}
],
"crs": { "type": "EPSG", "properties": { "code": 4326 } }
}
}
-
Las coordenadas:
"coordinates": [-64.471941, -23.643418]
-
Las localidad original que consultó:
"parsePattern" : "YUTO"
-
El radio de incerteza en metros:
"uncertaintyRadiusMeters" : 3036
-
El polígono de incerteza asociado:
"uncertaintyPolygon" : "Unavailable"
, en este caso no disponible. -
Los desplazamientos: distancia en millas y grados en una dirección:
"displacedDistanceMiles" : 0, "displacedHeadingDegrees" : 0
, en este caso con valores0
porque no se especifica desplazamiento de ningún tipo en la localidad (e.g., 45km de Yuto, o 45km N Yuto). -
La correspondencia en el gacetero consultado:
GazPartMatch
, y en éste la división administrativa bajo la cual se encontró la localidad:|:Adm=JUJUY|
.
Caso 3) Varios resultados encontrados para un mismo valor de localidad. Esto sucede comúnmente cuando no se especifican en la consulta niveles administrativos por debajo de país (e.g., podría haber en un mismo país varios lugares con el mismo nombre). Un ejemplo sería:
{
"engineVersion": "GLC:7.0|U:1.01374|eng:1.0",
"numResults": 3, (1)
"executionTimems": 468.7555,
"resultSet": {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [ -64.158097, -26.21252 ] (2)
},
"properties": {
"parsePattern": "TARTAGAL", (3)
"precision": "High",
"score": 83,
"uncertaintyRadiusMeters": 301,
"uncertaintyPolygon": "Unavailable",
"displacedDistanceMiles": 0,
"displacedHeadingDegrees": 0,
"debug": ":GazPartMatch=False|:inAdm=True|:Adm=SANTIAGO DEL ESTERO|:NPExtent=500|:NP=TARTAGAL|:KFID=|TARTAGAL" (4)
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [ -59.846115, -28.671732 ] (2)
},
"properties": {
"parsePattern": "TARTAGAL", (3)
"precision": "High",
"score": 83,
"uncertaintyRadiusMeters": 3036,
"uncertaintyPolygon": "Unavailable",
"displacedDistanceMiles": 0,
"displacedHeadingDegrees": 0,
"debug": ":GazPartMatch=False|:inAdm=True|:Adm=SANTA FE|:NPExtent=5040|:NP=TARTAGAL|:KFID=|TARTAGAL" (4)
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [ -63.801314, -22.516365 ] (2)
},
"properties": {
"parsePattern": "TARTAGAL", (3)
"precision": "High",
"score": 83,
"uncertaintyRadiusMeters": 3036,
"uncertaintyPolygon": "Unavailable",
"displacedDistanceMiles": 0,
"displacedHeadingDegrees": 0,
"debug": ":GazPartMatch=False|:inAdm=True|:Adm=SALTA|:NPExtent=5040|:NP=TARTAGAL|:KFID=|TARTAGAL" (4)
}
}
],
"crs": { "type": "EPSG", "properties": { "code": 4326 } }
}
}
Note que los tres resultados del ejemplo corresponden a provincias distintas en las que se encuentra una localidad “Tartagal”, puede comparar las coordenadas para cada una.
Note
|
Visualizando JSON
Para visualizar la estructura de los resultados en JSON de modo más amigable, puede probar copiando el resultado de alguna celda en un analizador de JSON en línea. Existen muchas opciones, una de ellas es http://json.parser.online.fr/. Allí, seleccionando distintas opciones arriba a la derecha podrá distinguir mejor la estructura, cuáles son los objetos, los arreglos y las cadenas de texto y cómo están relacionados unos con otros (Figura 51). Esto puede ser muy útil a la hora de armar expresiones para desglosar el contenido de los campos en nuevos campos sin perder información. |
Note
|
La expresión utilizada es muy simple y sólo le pide al servicio que resuelva la georreferenciación en base al campo localidad y teniendo como valor fijo “Argentina” para el campo país, pero sin especificar los valores de otros campos geográficos. Sin embargo, todos los campos se pueden incluir en la expresión para obtener resultados más específicos. Ello puede hacerse de dos maneras: |
-
Establecer los valores de los campos como valores fijos, como hicimos con el país, agregando luego por ejemplo:
&state=VALOR
donde VALOR es el valor fijo que uno establece (e.g., “Córdoba”). Esto restringirá los resultados en función de esos parámetros. -
Incluir los campos como valores a consultar, en cuyo caso para cada campo hay que incluir como valor:
escape(cells.NOMBREDELCAMPO.value,'url')
La expresión con todos los campos se verá entonces como:
"http://www.geo-locate.org/webservices/geolocatesvcv2/glcwrap.aspx?country=Argentina&state=" +
escape(cells.stateProvince.value,'url')+"&locality="+escape(cells.locality.value,'url')
Note que el nombre del campo será el que tiene en su base de datos. Note también que en la base de datos dada para este ejercicio no hay un campo correspondiente a "county"
, pero GEOLocate permite incluirlo si lo hubiera.
Para poder trabajar con estos resultados más cómodamente, debemos extraer de allí los valores de interés. En este paso debe tener cuidado. Debido a que no especificamos todos los campos geográficos en la consulta a GEOLocate, recuerde que los registros pueden tener más de un resultado posible, y que cada resultado tiene sus propios parámetros de georreferenciación.
A modo de ejemplo, extraeremos en nuevos campos los valores de las coordenadas. (El conjunto de datos provisto para realizar los ejercicios de esta guía contiene campos originales de latitud y longitud provistos por la fuente, puede utilizarlos para contrastar los resultados obtenidos utilizando GEOLocate).
Para extraer las coordenadas puede seguir dos métodos: 1) extraer latitud y longitud conjuntamente y luego separar; o 2) extraer latitud y longitud de modo independiente.
Método 1: extraer latitud y longitud conjuntamente
Haga click en menu:la ▼ azul del campo {geolocate_json_georref}[Editar columnas > Agregar columna basada en esta columna].
De un nombre al nuevo campo, por ejemplo, GeoLocate_parseCoord, y en el cuadro de texto pegue la siguiente expresión:
forEach(filter(value.parseJson().resultSet.features, v, isNonBlank(v.geometry)), w,
w.geometry.coordinates.join("; "))
.join("|")
Esta expresión es un poco más compleja que las que hemos estado utilizando, debido a que se requiere extraer información de una estructura JSON particular Objeto → Arreglo → Objeto → Arreglo. (Puede visualizar la estructura en JSON como se menciona en la nota de la Figura 51).
El nuevo campo tendrá valores como los siguientes, por ejemplo, para un registro cuya consulta devolvió tres resultados:
-64.158097; -26.21252|-59.846115; -28.671732|-63.801314; -22.516365
Important
|
Note que GEOLocate provee como primer valor de coordenadas la longitud y como segundo valor la latitud. |
Dividiremos ahora este campo en tres partes, una para cada resultado:
Haga click en "la ▼ azul del campo > Editar columnas > Dividir en varias columnas".
Escoja como separador |
. Desmarque la opción “Eliminar esta columna” si quiere mantener el campo original (esto es recomendable, siempre puede eliminar los campos después).
Tendrá entonces ahora una serie de campos con valores del tipo: -64.158097; -26.21252
. Sobre cada uno, puede realizar una nueva separación utilizando como separador ;
.
Método 2: extraer latitud y longitud independientemente
Haga click en menu:la ▼ azul del campo {geolocate_json_georref}[Editar columnas > Agregar columna basada en esta columna].
De un nombre al nuevo campo, por ejemplo, GeoLocate_parseLong, y en el cuadro de texto pegue la siguiente expresión:
forEach(filter(value.parseJson().resultSet.features, v, isNonBlank(v.geometry)), w,
w.geometry.coordinates[0]).join("; "))
Esta expresión es diferente a la usada anteriormente en que se especifica qué valor del arreglo coordenadas se desea obtener: [0]
. En OpenRefine, el primer valor se indica con 0, el segundo con 1, y así sucesivamente. Dado que en los resultados de la consulta se indica primero la longitud, ésta será el valor [0]
, y la latitud será el valor [1]
dentro del arreglo “coordinates”.
El nuevo campo creado tendrá valores como los siguientes: -64.158097; -59.846115; -63.801314
cada uno correspondiente a una longitud de uno de los resultados obtenidos de la consulta a GEOLocate para un determinado registro.
Puede repetir el proceso para obtener las latitudes, cambiando en la expresión anterior [0]
por [1]
, y luego separar los campos por resultado, utilizando como separador ;
.
Important
|
Debe tener en cuenta que, como se mencionó antes, cuantos más datos se provean al servicio de GEOLocate en la consulta más sencillo será desglosar los resultados después. El proceso de desglose puede ser muy engorroso y requiere que sea muy meticuloso/a a la hora de nombrar campos y separar contenido. Si no está familiarizado/a con el uso de JSON, es preferible que realice el desglose “pasito a pasito” para evitar perder o mezclar información. Por ejemplo, puede crear un documento con el flujo de trabajo donde enumere los pasos a seguir con todos los detalles necesarios (incluya allí el tipo de resultados que espera ver y cómo se verían en los campos). |
Important
|
A la hora de agregar datos de georreferenciación, contraste siempre los resultados contra los campos geográficos que tiene. En el caso de tener varios resultados posibles, no siempre el primer resultado es el correcto. Recuerde reportar cuál fue el proceso de georreferenciación utilizado y todos los parámetros posibles asociados. Para consultar en qué campos de Darwin Core se reporta cada parámetro, puede referirse a: https://dwc.tdwg.org/terms/#location, y consultar: https://github.com/tdwg/dwc-qa/wiki/Georeferences. |
Note
|
Para conocer más acerca de georreferenciación y las mejores prácticas asociadas, consulte Georeferencing Best Practices (Chapman & Wieczorek 2020). |
Uno de los campos sobre el que se puede corroborar la calidad de los datos es el campo de fecha: "eventDate"
.
Recordemos primero la definición de "eventDate"
en el estándar Darwin Core:
The date-time or interval during which an Event occurred. For occurrences, this is the date-time when the event was recorded. Not suitable for a time in a geological context. Recommended best practice is to use a date that conforms to ISO 8601-1:2019.
Si piensa en un ejemplar de museo, "eventDate"
refiere a cuándo fue colectado el ejemplar. Si piensa en una observación, "eventDate"
refiere a cuándo fue realizada esa observación.
Darwin Core sugiere que se utilice para capturar la información de fecha el estándar ISO 8601-1:2019. Para fechas únicas, este estándar tiene el siguiente formato:
AAAA-MM-DDTHH:mmX
Donde:
-
AAAA
: año, con cuatro dígitos. -
MM
: mes, con dos dígitos. E.g.: mayo sería 05. -
DD
: día, con dos dígitos. E.g.: segundo día de un mes sería 02. -
T
: indica que lo que viene a continuación es la hora. -
HH
: horas, con dos dígitos, en formato de 24 hs. -
mm
: minutos, con dos dígitos. -
X
: indica la zona horaria. La zona horaria se determina tomando como base UTC (Coordinated Universal Time). Si uno está justo sobre la zona horaria UTC, X se reemplaza por “Z”. Si uno está en otra zona horaria, debe reemplazarse X por la diferencia horaria correspondiente.
Por ejemplo, Argentina es UTC-3, o sea, 03horas00minutos al oeste (-) de UTC, por lo cual X debe reemplazarse por “-0300”.
Note
|
De este formato, uno puede utilizar tanto el formato completo (incluyendo la hora) como sólo la primera parte, AAAA-MM-DD. |
Note
|
Este formato también puede utilizarse para expresar rangos de fecha de manera estandarizada. Para ello, se usa el mismo formato y se separan las fechas con barras “/”, ver ejemplos abajo (Tabla 3). |
Tabla 3. Ejemplos de formatos de fechas y su versión estandarizada.
Fecha original | Fecha estandarizada |
---|---|
12 Feb 1809 |
1809-02-12 |
12/02/1809 |
1809-02-12 |
Jun 1906 |
1906-06 |
1971 |
1971 |
20 Feb 2009 8:40am UTC |
2009-02-20T08:40Z |
8 Mar 1963 2:07pm, en la zona horaria 6 horas más temprano que UTC |
1963-03-08T14:07-0600 |
13-15 Nov 2007 |
2007-11-13/15 |
1 Mar 2007 1pm UTC – 11 May 2008 3:30pm UTC |
2007-03-01T13:00:00Z/2008-05-11T15:30:00Z |
Muchas veces, a pesar de lo que indica el estándar Darwin Core, encontramos en el campo "eventDate"
fechas que no siguen el formato sugerido. Para estandarizarlas, puede hacer uso de la herramienta que ofrece Canadensys: Date Parsing.
Esta herramienta permite interpretar fechas, devolviéndolas en formato estándar. Ejemplos de los tipos de valores que puede interpretar son:
-
Jun 13, 2008
-
15 Jan 2011
-
2009 IV 02
-
2 VII 1986
Algunas fechas, sin embargo no las interpreta, veamos el siguiente ejemplo (Figura 52):
En las dos líneas inferiores, “13” sólo puede referir a días, pues no hay un mes “13”.
En las dos líneas superiores, en cambio, “2” y “4” pueden ambos referir a mes y día. Como en distintas partes del mundo se utilizan sistemas distintos (primero se pone día y luego mes, o viceversa), la herramienta no puede determinar inequívocamente cuál es cuál, y por ende no hace la interpretación.
Debe tener esto en cuenta cuando utilice la herramienta para limpiar los datos.
Ahora sí, invocaremos Date Parsing desde OpenRefine. Para ello, primero seleccione algunas fechas mediante una faceta, para reducir el tiempo de consulta. Luego, sobre la columna "eventDate"
haga click en "la ▼ azul > Editar columna > Agregar columna accediendo a URLs…" (Figura 53). En la ventana que aparece, nombre la nueva columna (por ejemplo “Canadensys_eventDate”) y pegue en el cuadro de texto la siguiente expresión:
"http://data.canadensys.net/tools/dates.json?data="+escape(cells["eventDate"].value,"url")
Esta expresión le indica a la herramienta que evalúe los valores del campo "eventDate"
y que devuelva los resultados en formato JSON.
Note
|
La limpieza puede tomar bastante tiempo, incluso horas, sea paciente… váyase a almorzar, o incluso a dormir y lo revisa al día siguiente… Cuando vuelva, encontrará el nuevo campo con los valores estandarizados! En formato JSON… (Figura 54). |
Fíjese que en el primer caso de la figura, Canadensys ha podido resolver la fecha, mientras que en el segundo caso no ha podido, dado que no puede interpretar inequívocamente “6” y “4” como día y mes o viceversa (como se explica más arriba). Ahora que tiene el resultado en formato JSON, extraeremos de allí los valores de interés. Podría extraer sólo la fecha en formato ISO, o también año, mes y día en campos separados. Para ello, a partir de la columna que tiene el resultado en JSON, cree nuevas columnas: "Editar columnas > Agregar columna basada en esta columna" (Figura 55).
Para extraer sólo la fecha en formato ISO, en la ventana nombre la nueva columna (por ejemplo, "ISO_eventDate") y en el cuadro de texto pegue la siguiente expresión:
forEach(value.parseJson().get("data").get("results"),v,v.get("iso8601"))[0])
Para extraer el año, mes o día, pegue en cambio una de las siguientes expresiones:
-
Año:
forEach(value.parseJson().get("data").get("results"),v,v.get("year"))[0])
-
Mes:
forEach(value.parseJson().get("data").get("results"),v,v.get("month"))[0])
-
Día:
forEach(value.parseJson().get("data").get("results"),v,v.get("day"))[0])
Verá que algunos de los resultados serán nulos, éstos corresponden a los casos que Canadensys no ha podido resolver (como se explica más arriba) (Figura 56).
Para terminar de limpiar las fechas, entonces, tendrá que revisar los valores que no hayan sido estandarizados por la herramienta. Para ello, sobre el campo ISO_eventDate puede armar una faceta y seleccionar el valor “blank”. Luego, arme una faceta sobre el campo "eventDate"
(el que tenía los valores originales) y si estos son pocos, puede hacer un chequeo manual y completar el campo ISO_eventDate.
Note
|
Transformación de fechas usando expresiones regulares
La consulta del servicio de Canadensys Date Parsing es particularmente útil cuando se tienen en un mismo campo fechas con distintos formatos, pues permite resolverlas todas utilizando un único proceso.
En cambio, si todas las fechas están dadas en un único formato, resulta más rápido realizar transformaciones utilizando expresiones regulares. Para ello, a partir de la columna con fechas a estandarizar, por ejemplo value.toDate("formato_original").toString("yyyy-MM-dd") donde en lugar de “formato_original” debe colocar el formato utilizado en el campo a estandarizar, considerando el orden en que aparecen el año, mes y día, el número de dígitos de cada uno y los separadores utilizados (e.g., guión, barra, etc.). Por ejemplo, si las fechas originales están todas escritas de la forma “mes/día/año”, la expresión a utilizar sería: value.toDate("MM/dd/yyyy").toString("yyyy-MM-dd") Con el formato especificado arriba, la expresión convertirá por ejemplo una fecha “04/25/1989” a “1989-04-25”. Recordar que esta opción solo será útil aplicada a una columna si todas las fechas en esa columna tienen el mismo formato. |