2
votes

Combinez deux listes lors de la création du dataframe R

J'ai la situation suivante avec deux liste : Chemin et UTMZones

>     UTMZones[lengths(UTMZones) == 0] <- ""
> library(tidyverse)
> df<-enframe(Path, name = "number", value = "uri") %>%
+       mutate(UTM  = UTMZones) %>%
+       unnest %>%  
+       mutate(plugin = ifelse(substr(uri, 11, 12) == "S1", 
+                              "class org.esa.s1tbx.io.sentinel1.Sentinel1ProductReaderPlugIn", 
+                              paste0("class org.esa.s2tbx.dataio.s2.ortho.plugins.Sentinel2L1CProduct_Multi_UTM", 
+                                     UTM, "N_ReaderPlugIn", collapse = "")))
> df$plugin[[3]]
[1] "class org.esa.s2tbx.dataio.s2.ortho.plugins.Sentinel2L1CProduct_Multi_UTMN_ReaderPlugInclass org.esa.s2tbx.dataio.s2.ortho.plugins.Sentinel2L1CProduct_Multi_UTM30N_ReaderPlugInclass org.esa.s2tbx.dataio.s2.ortho.plugins.Sentinel2L1CProduct_Multi_UTM18N_ReaderPlugIn"

La deuxième liste (le Null est correct)

> df
# A tibble: 5 x 3
  number uri                                                                     plugin                                                                      
   <int> <chr>                                                                   <chr>                                                                       
1      1 /home/rus/S1A_IW_GRDH_1SDV_20190824T003615_20190824T003640_028704_033F? class org.esa.s1tbx.io.sentinel1.Sentinel1ProductReaderPlugIn               
2      2 /home/rus/S2A_MSIL2A_20190827T105621_N0213_R094_T30TVK_20190827T141656? class org.esa.s2tbx.dataio.s2.ortho.plugins.Sentinel2L1CProduct_Multi_UTM30...
3      3 /home/rus/S2B_MSIL2A_20190826T153819_N0213_R011_T18TXL_20190826T195901? class org.esa.s2tbx.dataio.s2.ortho.plugins.Sentinel2L1CProduct_Multi_UTM18...

En utilisant ceci comme entrée, je crée un df avec le code suivant:

for (i in seq_along(Path)){
      for(j in seq_along(UTMZones)){

        df<-enframe(Path[[i]], name = "number", value = "uri") %>%
        unnest %>%
        mutate(plugin = case_when(substr(uri, 11, 12) == "S1" ~ "class org.esa.s1tbx.io.sentinel1.Sentinel1ProductReaderPlugIn", TRUE ~ paste0("class org.esa.s2tbx.dataio.s2.ortho.plugins.Sentinel2L1CProduct_Multi_UTM", UTMZones[[j]], "N_ReaderPlugIn", collapse = "")))

      }
    }

Le code fonctionne mais maintenant je dois insérer une petite modification. Dans la dernière partie du code, lors de la création du dataframe que je suis en train de faire

 ~ paste0("class org.esa.s2tbx.dataio.s2.ortho.plugins.Sentinel2L1CProduct_Multi_UTM", UTMZones, "N_ReaderPlugIn", collapse = "")))

Ce code ne fonctionne bien sûr pas. Ce que j'essaie de faire, c'est que lors de la création du df , pour la position [i] dans Path , la première position de UTMZones (par exemple, [j] doit être utilisé dans la fonction coller

J'ai essayé avec un à deux variables pour boucle mais je n'obtiens pas le bon résultat:

df<-enframe(Path, name = "number", value = "uri") %>%
        unnest %>%
        mutate(plugin = case_when(substr(uri, 11, 12) == "S1" ~ "class org.esa.s1tbx.io.sentinel1.Sentinel1ProductReaderPlugIn", TRUE ~ "class org.esa.s2tbx.dataio.s2.ortho.plugins.Sentinel2L1CProduct_Multi_UTM18N_ReaderPlugIn"))

- EDIT -

La sortie devrait ressembler à ceci. Notez comment les UTM changent dans l'ordre en utilisant UTMZones comme référence.

> UTMZones
[[1]]
NULL

[[2]]
[1] "30"

[[3]]
[1] "18"

- EDIT 2 -

Ceci est l'exécution du code avec la solution @Ronak Shah

> Path
[[1]]
[1] "/home/rus/S1A_IW_GRDH_1SDV_20190824T003615_20190824T003640_028704_033FD2_7CC8.SAFE/"

[[2]]
[1] "/home/rus/S2A_MSIL2A_20190827T105621_N0213_R094_T30TVK_20190827T141656.SAFE/"

[[3]]
[1] "/home/rus/S2B_MSIL2A_20190826T153819_N0213_R011_T18TXL_20190826T195901.SAFE/"


2 commentaires

À quoi ressemblerait votre résultat attendu?


@RonakShah J'ai édité la question pour montrer à quoi devrait ressembler la sortie


3 Réponses :


1
votes

Peu de changements dans le code. Remplacez d'abord les éléments NULL par des éléments vides

library(tidyverse)

enframe(Path, name = "number", value = "uri") %>%
    mutate(UTM  = UTMZones) %>%
    unnest %>%  
    mutate(plugin = ifelse(substr(uri, 11, 12) == "S1", 
    "class org.esa.s1tbx.io.sentinel1.Sentinel1ProductReaderPlugIn", 
paste0("class org.esa.s2tbx.dataio.s2.ortho.plugins.Sentinel2L1CProduct_Multi_UTM", 
            UTM, "N_ReaderPlugIn")))

puis incluez UTMZones dans le dataframe pour qu'il soit facile de remplacer les valeurs.

UTMZones[lengths(UTMZones) == 0] <- ""


7 commentaires

Je vois, j'essayais de créer des boucles pour ou d'itérer en utilisant lapply mais c'est plus droit. La seule chose est que votre code ajoute une quatrième colonne appelée UTM dans le dataframe .


@GCGM Donc, si ce n'est pas nécessaire, ajoutez %>% select (-UTM) à la fin?


J'ai modifié la question pour ajouter quelque chose qui ne fonctionne pas avec votre code


@GCGM Je ne suis pas sûr de comprendre votre modification. Si je stocke le résultat ci-dessus dans df . Pour moi, df $ plugin [2] renvoie [1] "class org.esa.s2tbx.dataio.s2.ortho.plugins.Sentinel2L1CProduct_Mu‌ lti_UTM30N_ReaderPlu‌ gIn" et < code> df $ plugin [3] [1] "classe org.esa.s2tbx.dataio.s2.ortho.plugins.Sentinel2L1CProduct_Mu‌ lti_UTM18N_ReaderPlu‌ gIn"


étrange, j'ai vérifié deux fois et je comprends toujours cela.


J'ai essayé de reproduire mais cela semble fonctionner pour moi comme mentionné dans le commentaire ci-dessus.


J'ai publié la sortie de l'exécution de votre code pour voir si nous trouvons où est le problème



1
votes

Nous pouvons le faire dans base R

transform(stack(setNames(Path, seq_along(Path)))[2:1], 
    plugin= ifelse(substr(values, 11, 12) == "S1", 
 "class org.esa.s1tbx.io.sentinel1.Sentinel1ProductReaderPlugIn", 
    paste0("class org.esa.s2tbx.dataio.s2.ortho.plugins.Sentinel2L1CProduct_Multi_UTM", 
         unlist(UTMZones), "N_ReaderPlugIn")))

Si nous n'avons pas besoin de la colonne 'UTM'

UTMZones <- lapply(UTMZones, function(x) replace(x, is.null(x), ""))
within(stack(setNames(Path, seq_along(Path)))[2:1],{ UTM <- unlist(UTMZones);plugin <- ifelse(substr(values, 11, 12) == "S1", 
 "class org.esa.s1tbx.io.sentinel1.Sentinel1ProductReaderPlugIn", 
    paste0("class org.esa.s2tbx.dataio.s2.ortho.plugins.Sentinel2L1CProduct_Multi_UTM", 
         UTM, "N_ReaderPlugIn"))})


10 commentaires

semble fonctionner. Seulement pour noter qu'à l'intérieur du paste0 doit être UTMZones et non UTM la variable utilisée. De plus, comme avec la solution de @Ronak, une colonne supplémentaire UTM est créée. C'est bien, je peux simplement supprimer mais je me demande où dans votre code cette colonne est créée


@GCGM En fait, nous n'avons pas besoin de la colonne UTM dans le ifelse , vous pouvez directement utiliser unlist (UTMZones) au lieu de créer le colonne


Juste pour clarifier, que fait le [2: 1] au début du code?


@GCGM C'est juste que les colonnes sont réorganisées avec la colonne 'ind' en premier Par exemple stack (setNames (Path, seq_along (Path))) output et stack (setNames (Path, seq_along (Chemin))) [2: 1] Par défaut, la stack renvoie la colonne 'values' comme première colonne


Belle astuce merci! J'aime le fait d'avoir la solution avec base


Au fait, je vois ici que les colonnes du datafram sont appelées ind values ​​ et plugin . Je pourrais les renommer par la suite, mais est-il possible lors de la création du dataframe de définir leurs noms sur number uri et pluging


@GCGM Oui, vous pouvez utiliser setNames (stack (...) [2: 1], c ("number", "uri"))


Je reçois ) inattendu ... je ne sais pas comment procéder


@GCGM Je voulais dire setNames (stack (setNames (Path, seq_along (Path))) [2: 1], c ("number", "url")) Peut-être avez-vous un ) ajouté à la fin


pourriez-vous l'ajouter au code dans la réponse. J'ai essayé d'ajouter la partie c ("number", "url")) de différentes manières, en vérifiant soigneusement la fermeture ) et j'obtiens différents types d'erreurs



1
votes

Bien que les réponses @akrun et @Ronak Shah soient beaucoup plus efficaces et c'est certainement ce que je recherche, je vais poser ma tentative - pas parfaite - qui est beaucoup plus basique mais je dirais facile à suivre au cas où quelqu'un est intéressé.

Comme je n'arrivais pas à itérer correctement dans le dataframe, une fois que le dataframe avait été créé avec un mauvais contenu pour la colonne plugin , j'ai utilisé le code suivant pour le corriger.

for (i in seq_along(Path)){
      if (substr(Path[[i]], 11,12) == 'S1') {
        df$plugin[[i]] <- 'class org.esa.s1tbx.io.sentinel1.Sentinel1ProductReaderPlugIn'
      } else {
        df$plugin[[i]] <- paste0("class org.esa.s2tbx.dataio.s2.ortho.plugins.Sentinel2L1CProduct_Multi_UTM", UTMZones[[i]], "N_ReaderPlugIn", collapse = "")
      }
    }


0 commentaires