Besoin de conseils remplacer as.matrix par getValues ?

Postez ici vos questions, réponses, commentaires ou suggestions - Les sujets seront ultérieurement répartis dans les archives par les modérateurs

Modérateur : Groupe des modérateurs

Céline Barrier
Messages : 14
Enregistré le : 30 Mai 2018, 11:49

Besoin de conseils remplacer as.matrix par getValues ?

Messagepar Céline Barrier » 03 Juin 2020, 13:23

Bonjour à tous,

J'ai un problème de mémoire lié à la fonction as.matrix

Suivant les conseils de la doc (https://www.rdocumentation.org/packages ... /as.matrix) j'aimerais utiliser les fonctions getValues ou getValuesBlock en espérant que cela résolve mon problème mais je ne sais pas trop comment m'y prendre.

L'erreur concernant la mémoire arrivait à la partie du script suivante :
##Obtenir une seule couche de données, créer un dataframe sur R et écrire un fichier .csv
# obtenir une seule tranche de données
temp_slice <- temp_array[4]
# Création du dataframe -- remodeler les données
# matrix (nlon*nlat rows by 2 cols) of lons and lats
## Permet de créer la matrice avec une colonne lat et lon
lonlat <- as.matrix(expand.grid(lon,lat))
dim(lonlat)
Erreur : impossible d'allouer un vecteur de taille 980,0 Go
Execution arrêtée


Mon script est le suivant :

Code : Tout sélectionner

#Script_test_extraire_temperature_netcdf

#Library
library(ncdf4)

#Charger rep.de travail
setwd("/gpfs/home/...")
dir()

#Ouverture du fichier netCDF
nc <-nc_open("nom_du_fichier.nc")
print(nc)

##Obtenir les coordonnées x, y de la variable
#obtenir la longitude
lon <- ncvar_get(nc,"longitude")
nlon <- dim(lon)
dim(lon)                  #donne la taille du vecteur
head(lon)                  #montre les données de longitude

#obtenir la latitude
lat <- ncvar_get(nc,"latitude")
nlat <- dim(lat)
dim(lat)                  #donne la taille du vecteur
head(lat)                  #montre les données de latitude
print(c(nlon,nlat))               #pour vérif. le nb de valeurs contenues dans les 2 dim.



# Obtenir le temps
time <- ncvar_get(nc,"time")

# Obtenir le temps + unité
tunits <- ncatt_get(nc,"time","units")
tunits

#Obtenir la variable température "TEMP"
dname <- "TEMP"
dname

# Obtenir la température
##Présente la matrice de données
temp_array <- ncvar_get(nc,dname)             
dlname <- ncatt_get(nc,dname,"long_name")      #"long_name" c'est la façon dont est nommée TEMP
dlname
dunits <- ncatt_get(nc,dname,"units")
dunits

##Indique le nombre de valeurs
fillvalue <- ncatt_get(nc,dname,"_FillValue")
fillvalue
dim(temp_array)
print(temp_array)

# Echelle de la temperature
min(na.omit(as.vector(temp_array[4])))
max(na.omit(as.vector(temp_array[4])))

# Fermer le netCDF
nc_close (nc)


##Obtenir une seule couche de données, créer un dataframe sur R et écrire un fichier .csv
# obtenir une seule tranche de données
temp_slice <- temp_array[4]
# Création du dataframe -- remodeler les données
# matrix (nlon*nlat rows by 2 cols) of lons and lats
## Permet de créer la matrice avec une colonne lat et lon
lonlat <- as.matrix(expand.grid(lon,lat))
dim(lonlat)

# vecteur de valeurs `temperature`
temp_vec <- as.vector(temp_slice)
length(temp_vec)

# Créer un dataframe et ajouter des noms
## On colle notre matrice avec lon et lat au vecteur temp
temp_df01 <- data.frame(cbind(lonlat,temp_vec))

## Dans sep ="" indiquer le nom de notre variable, ici temp
names(temp_df01) <- c("longitude","latitude", sep="TEMP")

##Permet de voir les 10 premières lignes notre tableau sans les NA
head(na.omit(temp_df01), 10)

#Sélection de la zone d’étude d’un point de vue spatial
#La fonction subset, est utilisée afin de ce centrer sur la zone souhaité et ainsi réduire le poids du fichier csv final
##Sélectionner une zone spatiale
## Ici on indique la zone spatiale de la Corse
temp_df01 <- subset(temp_df01, lon >= 8 & lon <= 10.5)
temp_df01 <- subset(temp_df01, lat >= 41 & lat <= 43.5)

##Ecrire le dataframe
#la trame de données est écrite dans le répertoire de travail sous forme de fichier .csv, en utilisant à nouveau na.omit () pour supprimer les observations avec des données manquantes.

# définir le chemin et le nom de fichier
csvpath <- "/gpfs/home/UDCPP/barrier_c/Test_CMS/data_brut/MENOR1200/V10-SN/2017"

##Ici, on peu remplacer csv par .txt si on veut un format texte
csvname <- "Temp.csv"
csvfile <- paste(csvpath, csvname, sep="")
write.table(na.omit(temp_df01),csvfile, row.names=FALSE, sep=",")

##Vérifier les données
#Afin de vérifier notre .csv, nous allons réaliser un raster des données de temperature

#Librairie
library(ggplot2)

setwd("/gpfs/home/UDCPP/barrier_c/Test_CMS/data_brut/MENOR1200/V10-SN/2017")
test <- read.csv("Temp.csv", header = T, sep =",")

ggplot(data = test, aes(x = lon, y = lat, fill = temp)) +
geom_raster(interpolate = TRUE) +
scale_fill_viridis_c(begin = 0, end =1) +
theme_bw() +
coord_fixed(1.3)



Mon fichier se trouve ici > https://drive.google.com/file/d/1siVwKquNLrr7vsJBXfwLCS7mNKCty_AI/view?usp=sharing

Mon objectif est de pouvoir exprimer les température du fichier (la variable TEMP), chaque jour, dans un graphe ou un dataframe en sortie .csv ou .txt

Merci pour votre aide/vos conseils !

Logez Maxime
Messages : 3138
Enregistré le : 26 Sep 2006, 11:35

Re: Besoin de conseils remplacer as.matrix par getValues ?

Messagepar Logez Maxime » 03 Juin 2020, 13:39

Bonjour,

ton volume de données semble très grand et via la fonction expand.grid tu cherches à générer toutes les combinaisons possibles de latitude et de longitude ce qui peut tout de suite être très volumineux. Est-ce que tu es sur que ce n'est pas ça le problème plus que le as.matrix ? As-tu essayé le expand.grid seul ?

Cordialement,
Maxime

Céline Barrier
Messages : 14
Enregistré le : 30 Mai 2018, 11:49

Re: Besoin de conseils remplacer as.matrix par getValues ?

Messagepar Céline Barrier » 03 Juin 2020, 14:26

Bonjour!
Oui en effet, c'est expand.grid qui est concerné.
D'après ce que je peux voir, il faut soit que j'implémente une boucle (mais dans mon cas je ne vois pas comment et surtout si c'est pertinent), soit que je passe sur python.
Qu'en pensez-vous ?

François Bonnot
Messages : 537
Enregistré le : 10 Nov 2004, 15:19
Contact :

Re: Besoin de conseils remplacer as.matrix par getValues ?

Messagepar François Bonnot » 03 Juin 2020, 14:39

Bonjour,
Si expand.grid manque de mémoire, il risque d'en être de même pour la matrice.
Vous devriez avant de vous lancer dans une boucle voir s'il est possible d'allouer une matrice de la dimension finale remplie avec la même valeur numérique par exemple.
François

Céline Barrier
Messages : 14
Enregistré le : 30 Mai 2018, 11:49

Re: Besoin de conseils remplacer as.matrix par getValues ?

Messagepar Céline Barrier » 03 Juin 2020, 15:11

Bonjour,
Merci pour ce retour,
Pouvez-vous m'indiquer comment procéder?

François Bonnot
Messages : 537
Enregistré le : 10 Nov 2004, 15:19
Contact :

Re: Besoin de conseils remplacer as.matrix par getValues ?

Messagepar François Bonnot » 03 Juin 2020, 15:35

Pour créer par exemple une matrice de 10 lignes et 20 colonnes avec la valeur pi pour tous les éléments:

Code : Tout sélectionner

m <- matrix(pi, nrow=10, ncol=20)

Evidemment il faut remplacer 10 et 20 par vos nombres de lignes et de colonnes.
S'il n'y a pas d'erreur, la mémoire est suffisante.

Exemple d'erreur :

Code : Tout sélectionner

> m <- matrix(pi, nrow=100000, ncol=20000)
Error: cannot allocate vector of size 14.9 Gb
François

Céline Barrier
Messages : 14
Enregistré le : 30 Mai 2018, 11:49

Re: Besoin de conseils remplacer as.matrix par getValues ?

Messagepar Céline Barrier » 03 Juin 2020, 16:54

Merci, en effet la mémoire ne semble pas suffisante pour exécuter ce script.

Gabriel Terraz
Messages : 591
Enregistré le : 26 Sep 2011, 15:11

Re: Besoin de conseils remplacer as.matrix par getValues ?

Messagepar Gabriel Terraz » 03 Juin 2020, 20:27

Je rejoins le commentaire sur expand.grid, quel peut être l'intérêt de créer les combinaisons de deux vecteurs quantitatifs (longitude et latitude) ?
A quoi te sert cette étape ?

Céline Barrier
Messages : 14
Enregistré le : 30 Mai 2018, 11:49

Re: Besoin de conseils remplacer as.matrix par getValues ?

Messagepar Céline Barrier » 04 Juin 2020, 06:56

Bonjour,

Le but de la manip - qui a déjà fonctionné mais sur des fichiers plus légers - est d'extraire une variable d’intérêt (ici température), obtenir ses coordonnées x,y (long, lag), et le temps.

D'après le package utilisé pour traiter les fichiers type netcdf - netcdf4 - cette fonction permet d'obtenir une seule couche de données pour créer un dataframe, puis le réécrire en .csv ou .txt (le script a fonctionné pour d'autres fichiers moins volumineux).
lonlat, c'est parce qu'on souhaite remodeler les donnés, matrix (nlon*nlat rows by 2 cols) = faire une matrice avec une colonne lat et une colonne lon.
Ensuite cette matrice est "collée" au vecteur des températures pour créer notre dataframe.
temp_vec <- as.vector(temp_slice)
length(temp_vec)
temp_df01 <- data.frame(cbind(lonlat,temp_vec))
names(temp_df01) <- c("longitude","latitude", sep="TEMP")

Dans la suite du code, je sélectionne ma zone d'étude avec subset
temp_df01 <- subset(temp_df01, lon >= 8 & lon <= 10.5)
temp_df01 <- subset(temp_df01, lat >= 41 & lat <= 43.5)

Puis j'écris le dataframe soit en .csv soit en .txt
csvpath <- "/gpfs/xxx"
csvname <- "Temp.csv"
csvfile <- paste(csvpath, csvname, sep="")
write.table(na.omit(temp_df01),csvfile, row.names=FALSE, sep=",")

La fin du script est un plot des données pour voir à quoi elles ressemblent.

Logez Maxime
Messages : 3138
Enregistré le : 26 Sep 2006, 11:35

Re: Besoin de conseils remplacer as.matrix par getValues ?

Messagepar Logez Maxime » 04 Juin 2020, 07:18

Bonjour,

Pour passer d'une matrice au format "large" à une seule colonne, tu n'as pas besoin de recréer un jeu de données avec touts les combinaisons possibles. Tu peux simplement passer cette matrice en ligne. Une matrice n'est ni plus ni moins qu'un vecteur avec des dimensions, dont les colonnes sont remplies en séquentielles (on templit d'abord la première colonne, puis la deuxième, etc.). Donc on peut remettre à la suite les valeurs qui étaient en colonne :

Code : Tout sélectionner

x <- 1:12
mat <- matrix(x, nrow = 4)
mat
     [,1] [,2] [,3]
[1,]    1    5    9
[2,]    2    6   10
[3,]    3    7   11
[4,]    4    8   12

# si on supprime les dimensions de mat on récupère le vecteur des valeurs :
dim(mat) <- NULL
mat
[1]  1  2  3  4  5  6  7  8  9 10 11 12

# ce qui ressemble à
c(mat)
as.vector(mat)
Il convient ensuite de répéter soit le numero de la ligne soit le numéro de la colonne si on veut conserver ces informations dans un data.frame :

Code : Tout sélectionner

x <- 1:12
mat <- matrix(x, nrow = 4)
nr <- nrow(mat)
nc <- ncol(mat)
dim(mat) <- NULL
df <- data.frame(valeur = mat,
  nrow = rep(1:nr,  nc),
  ncol = rep(1:nc, each = nr))
df
   valeur nrow ncol
1       1    1    1
2       2    2    1
3       3    3    1
4       4    4    1
5       5    1    2
6       6    2    2
7       7    3    2
8       8    4    2
9       9    1    3
10     10    2    3
11     11    3    3
12     12    4    3
Cordialement,
Maxime


Retourner vers « Questions en cours »

Qui est en ligne

Utilisateurs parcourant ce forum : Google [Bot] et 1 invité