Comment créer une liste de blocs de données et comment accéder à chacun de ces blocs de données à partir de la liste?
Par exemple, comment puis-je mettre ces blocs de données dans une liste?
d1 <- data.frame(y1 = c(1, 2, 3),
y2 = c(4, 5, 6))
d2 <- data.frame(y1 = c(3, 2, 1),
y2 = c(6, 5, 4))
=
pas à l'<-
intérieurdata.frame()
. En utilisant<-
vous créezy1
ety2
dans votre environnement global et votre bloc de données n'est pas ce que vous voulez qu'il soit.<-
s à l'intérieur de data.frame (). Quel newb j'étais.Réponses:
Ce n'est pas lié à votre question, mais vous souhaitez utiliser
=
et non<-
dans l'appel de fonction. Si vous utilisez<-
, vous finirez par créer des variablesy1
ety2
dans n'importe quel environnement dans lequel vous travaillez:Cela n'aura pas l'effet apparemment souhaité de créer des noms de colonnes dans le bloc de données:
L'
=
opérateur, quant à lui, associera vos vecteurs aux arguments dedata.frame
.Quant à votre question, faire une liste de blocs de données est facile:
Vous accédez aux blocs de données comme vous accéderiez à tout autre élément de liste:
la source
Les autres réponses vous montrer comment faire une liste de data.frames lorsque vous avez déjà un tas de data.frames, par exemple
d1
,d2
.... Ayant successivement nommées trames de données est un problème, et de les mettre dans une liste est une bonne solution, mais la meilleure pratique est d' éviter d'avoir un tas de data.frames pas dans une liste en premier lieu.Les autres réponses donnent beaucoup de détails sur la façon d'attribuer des trames de données à des éléments de liste, d'y accéder, etc. Nous aborderons cela un peu ici aussi, mais le point principal est de dire n'attendez pas d'avoir un tas de
data.frames
pour les ajouter à une liste. Commencez par la liste.Le reste de cette réponse couvrira certains cas courants où vous pourriez être tenté de créer des variables séquentielles et vous montrera comment accéder directement aux listes. Si vous êtes nouveau dans les listes de R, vous voudrez peut-être également lire Quelle est la différence entre
[[
et[
dans l'accès aux éléments d'une liste? .Listes depuis le début
Ne créez jamais
d1
d2
d3
, ...dn
en premier lieu. Créez une listed
avec desn
éléments.Lecture de plusieurs fichiers dans une liste de blocs de données
Cela se fait assez facilement lors de la lecture de fichiers. Peut-être avez-vous des fichiers
data1.csv, data2.csv, ...
dans un répertoire. Votre objectif est une liste de data.frames appeléemydata
. La première chose dont vous avez besoin est un vecteur avec tous les noms de fichiers. Vous pouvez le construire avec coller (par exemple,my_files = paste0("data", 1:5, ".csv")
), mais il est probablement plus facile à utiliserlist.files
pour récupérer tous les fichiers appropriés:my_files <- list.files(pattern = "\\.csv$")
. Vous pouvez utiliser des expressions régulières pour faire correspondre les fichiers, en savoir plus sur les expressions régulières dans d'autres questions si vous avez besoin d'aide. De cette façon, vous pouvez récupérer tous les fichiers CSV même s'ils ne suivent pas un bon schéma de dénomination. Ou vous pouvez utiliser un modèle de regex plus sophistiqué si vous avez besoin de sélectionner certains fichiers CSV parmi plusieurs d'entre eux.À ce stade, la plupart des débutants en R utiliseront une
for
boucle, et il n'y a rien de mal à cela, cela fonctionne très bien.Une façon plus R-like de le faire est avec
lapply
, qui est un raccourci pour ce qui précèdeBien sûr, remplacez par une autre fonction d'importation de données
read.csv
le cas échéant.readr::read_csv
oudata.table::fread
sera plus rapide, ou vous pouvez également avoir besoin d'une fonction différente pour un type de fichier différent.Dans tous les cas, il est pratique de nommer les éléments de la liste pour qu'ils correspondent aux fichiers
Fractionnement d'un bloc de données en une liste de blocs de données
C'est très simple, la fonction de base le
split()
fait pour vous. Vous pouvez diviser par une colonne (ou des colonnes) des données, ou par tout ce que vous voulezC'est également un bon moyen de diviser une trame de données en morceaux pour une validation croisée. Vous souhaitez peut-être vous diviser
mtcars
en éléments de formation, de test et de validation.Simulation d'une liste de trames de données
Peut-être que vous simulez des données, quelque chose comme ceci:
Mais qui fait une seule simulation? Vous voulez faire cela 100 fois, 1000 fois, plus! Mais vous ne voulez pas 10 000 blocs de données dans votre espace de travail. Utilisez-les
replicate
et mettez-les dans une liste:Dans ce cas en particulier, vous devez également vous demander si vous avez vraiment besoin de trames de données séparées ou si une seule trame de données avec une colonne "groupe" fonctionnerait tout aussi bien? En utilisant
data.table
ou,dplyr
il est assez facile de faire des choses "par groupe" dans un bloc de données.Je n'ai pas mis mes données dans une liste: (Je le ferai la prochaine fois, mais que puis-je faire maintenant?
S'il s'agit d'un assortiment étrange (ce qui est inhabituel), vous pouvez simplement les attribuer:
Si vous avez des trames de données nommées dans un modèle, par exemple,
df1
,df2
,df3
et vous les voulez dans une liste, vous pouvezget
les si vous pouvez écrire une expression régulière pour correspondre aux noms. Quelque chose commeGénéralement,
mget
est utilisé pour obtenir plusieurs objets et les renvoyer dans une liste nommée. Son équivalentget
est utilisé pour obtenir un seul objet et le renvoyer (pas dans une liste).Combinaison d'une liste de trames de données en une seule trame de données
Une tâche courante consiste à combiner une liste de trames de données en une seule trame Big Data. Si vous souhaitez les empiler les uns sur les autres, vous les utiliserez
rbind
pour une paire d'entre eux, mais pour une liste de blocs de données, voici trois bons choix:(De même en utilisant
cbind
oudplyr::bind_cols
pour les colonnes.)Pour fusionner (joindre) une liste de blocs de données, vous pouvez voir ces réponses . Souvent, l'idée est d'utiliser
Reduce
avecmerge
(ou une autre fonction de jonction) pour les réunir.Pourquoi mettre les données dans une liste?
Mettez des données similaires dans les listes parce que vous voulez faire des choses semblables à chaque trame de données et des fonctions telles que
lapply
,sapply
do.call
, l'purrr
emballage , et les anciennesplyr
l*ply
fonctions , il est facile de le faire. Des exemples de personnes faisant facilement des choses avec des listes sont partout SO.Même si vous utilisez une boucle for modeste, il est beaucoup plus facile de boucler sur les éléments d'une liste que de construire des noms de variables avec
paste
et d'accéder aux objets avecget
. Plus facile à déboguer également.Pensez à l' évolutivité . Si vous avez vraiment besoin de trois variables, il est bon d'utiliser
d1
,d2
,d3
. Mais s'il s'avère que vous avez vraiment besoin de 6, c'est beaucoup plus de frappe. Et la prochaine fois, quand vous avez besoin de 10 ou 20, vous vous surprenez à copier et coller des lignes de code, peut-être en utilisant find / replace pour passerd14
àd15
, et vous pensez que ce n'est pas comme ça que la programmation devrait être . Si vous utilisez une liste, la différence entre 3 cas, 30 cas et 300 cas est au plus une ligne de code --- aucun changement si votre nombre de cas est automatiquement détecté par, par exemple, combien.csv
fichiers dans votre annuaire.Vous pouvez nommer les éléments d'une liste, au cas où vous voudriez utiliser autre chose que des index numériques pour accéder à vos blocs de données (et vous pouvez utiliser les deux, ce n'est pas un choix XOR).
Dans l'ensemble, l'utilisation de listes vous amènera à écrire un code plus propre et plus facile à lire, ce qui entraînera moins de bogues et moins de confusion.
la source
r
etlist
.my_data <- NULL
plutôt que `my_data <- list () '! :)my_data <- list()
il est clair que vous créez une liste, ce qui est bien! Un code clair est une bonne chose. Je ne vois aucun avantage à utiliser à lamy_data <- NULL
place.names(my_data) <- gsub("\\.csv$", "", my_files)
;) <br> Mais je respecte vos conseils car j'apprends beaucoup d'eux en tant que débutant et je l'apprécie vraiment :)Vous pouvez également accéder à des colonnes et des valeurs spécifiques dans chaque élément de liste avec
[
et[[
. Voici quelques exemples. Tout d'abord, nous ne pouvons accéder qu'à la première colonne de chaque bloc de données de la liste aveclapply(ldf, "[", 1)
, où1
signifie le numéro de colonne.De même, nous pouvons accéder à la première valeur de la deuxième colonne avec
Ensuite, nous pouvons également accéder aux valeurs des colonnes directement, sous forme de vecteur, avec
[[
la source
Si vous avez un grand nombre de blocs de données nommés séquentiellement, vous pouvez créer une liste du sous-ensemble souhaité de blocs de données comme ceci:
où
my.list2
renvoie une liste contenant les 2e, 3e et 4e trames de données.Notez cependant que les blocs de données de la liste ci-dessus ne sont plus nommés. Si vous souhaitez créer une liste contenant un sous-ensemble de blocs de données et que vous souhaitez conserver leurs noms, vous pouvez essayer ceci:
qui renvoie:
la source
lapply(foo, get)
, utilisez simplementmget(foo)
En prenant pour acquis que vous avez un "grand" nombre de data.frames avec des noms similaires (ici d # où # est un entier positif), ce qui suit est une légère amélioration de la méthode de @ mark-miller. Il est plus laconique et renvoie une liste nommée de data.frames, où chaque nom de la liste est le nom du data.frame d'origine correspondant.
La clé utilise
mget
avecls
. Si les blocs de données d1 et d2 fournis dans la question étaient les seuls objets avec des noms d # dans l'environnement, alorsqui reviendrait
Cette méthode tire parti de l'argument pattern in
ls
, qui nous permet d'utiliser des expressions régulières pour faire une analyse plus fine des noms des objets dans l'environnement. Une alternative à l'expression régulière"^d[0-9]+$"
est"^d\\d+$"
.Comme le souligne @gregor , il est globalement préférable de configurer votre processus de construction de données de sorte que les data.frames soient placés dans des listes nommées au début.
Les données
la source
C'est peut-être un peu tard, mais pour revenir à votre exemple, j'ai pensé que je prolongerais un peu la réponse.
Ensuite, vous faites votre liste facilement:
Vous avez maintenant une liste mais au lieu d'accéder à la liste à l'ancienne, par exemple
vous pouvez utiliser cette fonction pour obtenir et attribuer la trame de données de votre choix.
Maintenant, prenez celui que vous voulez.
J'espère que ce petit plus vous aidera.
À votre santé!
la source
GETDF_FROMLIST(mylist, 1)
àmylist[[1]]
? Si vous préférez la syntaxe de fonction, vous pouvez même vous"[["(mylist, 1)
passer de la définition d'une fonction personnalisée.return(DF_LIST[[ITEM_LOC]])
, pas besoin d'attribuer une variable intermédiaire.Très simple ! Voici ma suggestion:
Si vous souhaitez sélectionner des dataframes dans votre espace de travail, essayez ceci:
ou
tout cela donnera le même résultat.
Vous pouvez changer
is.data.frame
pour vérifier d'autres types de variables commeis.function
la source
Je me considère comme un débutant complet, mais je pense avoir une réponse extrêmement simple à l'une des sous-questions originales qui n'a pas été énoncée ici: accéder aux blocs de données, ou à des parties de celui-ci.
Commençons par créer la liste avec les cadres de données comme indiqué ci-dessus:
Ensuite, si vous souhaitez accéder à une valeur spécifique dans l'un des blocs de données, vous pouvez le faire en utilisant les doubles crochets de manière séquentielle. Le premier ensemble vous amène dans le bloc de données, et le second ensemble vous amène aux coordonnées spécifiques:
la source