4 votos

Uso de rioxarray para asignar la referencia espacial (EPSG:4326) a NetCDF construido a partir de CSV con columnas lat long

Estoy intentando crear un NetCDF a partir de un archivo CSV. La idea viene del hecho de que el CSV original viene con muchas columnas, tres de estas representan:

  • un año específico ("tiempo")
  • la coordenada Y de la observación en EPSG:4326 ("latitud")
  • la coordenada X de la observación en EPSG:4326 ("longitud")

Como quiero poder inspeccionar dinámicamente cada variable en un momento dado como un mapa, quiero convertirlo a formato NetCDF.

Primero importo mi CSV en un DataFrame de Pandas, luego creo un MultiIndex con las tres dimensiones que necesito, lo convierto en un DataSet de xarray, escribo el CRS con rioxarray, y finalmente lo exporto a un archivo NetCDF nc.

import pandas as pd
import rioxarray
import xarray as xr

df = pd.read_csv('my_data.csv')
df = df.set_index(['time', 'latitude', 'longitude'])
ds = df.to_xarray()
ds.rio.write_grid_mapping(inplace=True)
ds.rio.write_crs("epsg:4326", inplace=True)
ds.to_netcdf('my_data.nc')

Sin embargo, cuando intento importarlo como capa de malla en QGIS, o en Panoply, las coordenadas de mi NetCDF no se ven correctamente (ver las imágenes de abajo).

Pensé que ds.rio.write_crs(4326, inplace=True) fue suficiente para wtite el CRS a mi conjunto de datos para que sea reconocido por otro software, pero eso no parece suficiente.

Realmente deseo hacerlo en Python para posiblemente evitar el uso de otro software externo.

Información de ds.info :

Dimensions:           (latitude: 144, longitude: 140, time: 9)
Coordinates:
  * time              (time) datetime64[ns] 1980-01-01 1985-01-01 ... 2020-01-01
  * latitude          (latitude) float64 -34.75 -34.25 -33.75 ... 36.25 36.75
  * longitude         (longitude) float64 19.75 19.25 20.25 ... -23.75 -24.75
    spatial_ref       int64 0
Data variables:
    GHS_DENS_5avg     (time, latitude, longitude) float64 0.4566 nan ... nan nan
    rural             (time, latitude, longitude) float64 1.0 nan ... nan nan
    cities            (time, latitude, longitude) float64 0.0 nan ... nan nan
    temp_meanavg      (time, latitude, longitude) float64 17.4 nan ... nan nan
    temp_anom_5y      (time, latitude, longitude) float64 -0.01 nan ... nan nan
    prec_meanavg      (time, latitude, longitude) float64 37.1 nan ... nan nan
    prec_anom_5y      (time, latitude, longitude) float64 1.16 nan ... nan nan
    best              (time, latitude, longitude) float64 nan nan ... nan nan
    type_of_violence  (time, latitude, longitude) float64 nan nan ... nan nan
    n_event           (time, latitude, longitude) float64 nan nan ... nan nan
    any_event         (time, latitude, longitude) float64 0.0 nan ... nan nan>

Información de Panoply:

netcdf file:/home/umberto/Documents/jrc/teleworking/ca/projects/fabrizio/ciclim/data/Conflict%20data/africa_nc_conflict.nc {
  dimensions:
    time = 9;
    latitude = 144;
    longitude = 140;
  variables:
    long time(time=9);
      :units = "days since 1980-01-01 00:00:00";
      :calendar = "proleptic_gregorian";

    double latitude(latitude=144);
      :_FillValue = NaN; // double

    double longitude(longitude=140);
      :_FillValue = NaN; // double

    String iso3(time=9, latitude=144, longitude=140);
      :coordinates = "";
      :grid_mapping = "spatial_ref";

    double GHS_DENS_5avg(time=9, latitude=144, longitude=140);
      :_FillValue = NaN; // double
      :grid_mapping = "spatial_ref";
      :coordinates = "";

    double rural(time=9, latitude=144, longitude=140);
      :_FillValue = NaN; // double
      :coordinates = "";
      :grid_mapping = "spatial_ref";

    double cities(time=9, latitude=144, longitude=140);
      :_FillValue = NaN; // double
      :coordinates = "";
      :grid_mapping = "spatial_ref";

    double temp_meanavg(time=9, latitude=144, longitude=140);
      :_FillValue = NaN; // double
      :long_name = "5yr mean temperature";
      :units = "°C";
      :coordinates = "";
      :grid_mapping = "spatial_ref";

    double temp_anom_5y(time=9, latitude=144, longitude=140);
      :grid_mapping = "spatial_ref";
      :_FillValue = NaN; // double
      :coordinates = "";

    double prec_meanavg(time=9, latitude=144, longitude=140);
      :_FillValue = NaN; // double
      :grid_mapping = "spatial_ref";
      :coordinates = "";

    double prec_anom_5y(time=9, latitude=144, longitude=140);
      :_FillValue = NaN; // double
      :coordinates = "";
      :grid_mapping = "spatial_ref";

    double best(time=9, latitude=144, longitude=140);
      :grid_mapping = "spatial_ref";
      :coordinates = "";
      :_FillValue = NaN; // double
      :long_name = "Number of deaths";
      :units = "count";

    double type_of_violence(time=9, latitude=144, longitude=140);
      :_FillValue = NaN; // double
      :coordinates = "";
      :grid_mapping = "spatial_ref";

    double n_event(time=9, latitude=144, longitude=140);
      :_FillValue = NaN; // double
      :long_name = "Number of conflict events";
      :coordinates = "";
      :grid_mapping = "spatial_ref";
      :units = "count";

    double any_event(time=9, latitude=144, longitude=140);
      :_FillValue = NaN; // double
      :long_name = "Conflict events";
      :coordinates = "";
      :grid_mapping = "spatial_ref";
      :units = "Presence of conflict";

    long spatial_ref;
      :crs_wkt = "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AXIS[\"Latitude\",NORTH],AXIS[\"Longitude\",EAST],AUTHORITY[\"EPSG\",\"4326\"]]";
      :semi_major_axis = 6378137.0; // double
      :semi_minor_axis = 6356752.314245179; // double
      :inverse_flattening = 298.257223563; // double
      :reference_ellipsoid_name = "WGS 84";
      :longitude_of_prime_meridian = 0.0; // double
      :prime_meridian_name = "Greenwich";
      :geographic_crs_name = "WGS 84";
      :grid_mapping_name = "latitude_longitude";
      :spatial_ref = "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AXIS[\"Latitude\",NORTH],AXIS[\"Longitude\",EAST],AUTHORITY[\"EPSG\",\"4326\"]]";netcdf file:/home/umberto/Documents/jrc/teleworking/ca/projects/fabrizio/ciclim/data/Conflict%20data/africa_nc_conflict.nc {
  dimensions:
    time = 9;
    latitude = 144;
    longitude = 140;

  // global attributes:
}

NetCDF as mesh in QGIS

NetCDF as mesh in Panoply

1voto

Randyaa Puntos 904

Gracias a la respuesta de @snowman2 En el caso de la versión en inglés, pude entender que el problema era que mis coordenadas no estaban bien ordenadas. Bueno, al menos parece que se ha resuelto el problema para Panoply y las parcelas que hago con Python, mientras que QGIS sigue sin mostrar la capa en la posición correcta (pero supongo que esto sería otra cuestión).

El código actualizado (con comentario para enfatizar la solución), es este:

import pandas as pd
import rioxarray
import xarray as xr

df = pd.read_csv('my_data.csv')
df = df.set_index(['time', 'latitude', 'longitude'])
ds = df.to_xarray()
ds = ds.sortby(["time", "latitude", "longitude"]) # THIS SOLVED THE PROBLEM
ds.rio.write_crs("epsg:4326", inplace=True)
ds.to_netcdf('my_data.nc')

Panoply: enter image description here

QGIS (sigue siendo malo, no sé por qué): enter image description here

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X