Je restructure des variables contenant des lectures de tension artérielle. Chaque lecture contient les valeurs systolique et diastolique séparées par une barre oblique (/). Pour cet exemple, il y a trois lectures par ligne (c'est-à-dire par personne).
La sortie que je veux est d'avoir des variables séparées pour les valeurs systoliques et diastoliques pour chaque lecture.
Voici l'exemple de données en csv:
Error in eval_tidy(enquo(var), var_env) : object 'v' not found
Après avoir chargé tidyverse, je peux le faire en utilisant séparément, pour chaque lecture, par exemple,
for (i in 1:3) {
blPr <- blPr %>% separate (v[i] , c('v[i]_sys' , 'v[i]_dias') , sep = '/' , remove = FALSE)
}
Cependant, étant donné que l'ensemble de données réel a plusieurs lectures supplémentaires par personne, je cherche à éliminer plusieurs lignes en utilisant une boucle for. Après avoir examiné quelques exemples sur le Web, j'ai essayé:
blPr <- read_csv('BlPr.csv')
blPr <- blPr %>% separate (v1 , c('v1_sys' , 'v1_dias') , sep = '/' , remove = FALSE)
Il a renvoyé le message d'erreur:
id,v1,v2,v3 1,116 / 77,121 / 68,105 / 76 2,164 / 67,171 / 79,155 / 68 3,146 / 109,, 4,120 / 80,102 / 64,137 / 87 5,112 / 50,130 / 40,
J'ai modifié le code de plusieurs manières, mais comme je ne comprends pas ce qui ne va pas, je me retrouve vide.
3 Réponses :
Ce code ci-dessous fonctionne ...
# Create dataframe
blPr = read.table(text = '
id,v1,v2,v3
1,116 / 77,121 / 68,105 / 76
2,164 / 67,171 / 79,155 / 68
3,146 / 109,,
4,120 / 80,102 / 64,137 / 87
5,112 / 50,130 / 40,
', header = T, sep = ",")
library(tidyr)
for (i in c(1:3)){
eval(parse(text=paste0(
"blPr <- blPr %>% separate (v",i," , c('v",i,"_sys' , 'v",i,"_dias') , sep = '/' , remove = FALSE)"
)))
}
Merci, le code a parfaitement fonctionné et a obtenu le résultat que je recherchais. J'aurai du travail à faire pour démonter le code et mieux le comprendre. Cela aidera à avoir cet exemple.
Super, je suis content que cela ait fonctionné. Pouvez-vous le marquer comme «correct»?
Ce que vous pouvez faire est de conserver toutes les lectures et de mettre les données dans un fomat bien rangé:
library(tidyverse) data <- read.table(text = ' id,v1,v2,v3 1,116 / 77,121 / 68,105 / 76 2,164 / 67,171 / 79,155 / 68 3,146 / 109,, 4,120 / 80,102 / 64,137 / 87 5,112 / 50,130 / 40, ', header = T, sep = ",")
Vous pouvez aller plus loin et a) supprimer les NA et b) les mettre sous forme longue: p >
result_wide <- result_long %>%
spread("reading_type", "value", drop = TRUE) %>%
unite("value", c("systolic", "diastolic"), sep = " / ") %>%
spread("reading", "value")
> result_wide
id v1 v2 v3
1 1 116 / 77 121 / 68 105 / 76
2 2 164 / 67 171 / 79 155 / 68
3 3 146 / 109 <NA> <NA>
4 4 120 / 80 102 / 64 137 / 87
5 5 112 / 50 130 / 40 <NA>
Les formats ordonnés facilitent grandement la gestion et le tracé des données. Il est également très facile de les remettre sous une forme lisible par l'homme. Le format choisi dans result est peut-être un bon compromis entre lisible par l'homme et facile à manipuler.
library(ggplot)
ggplot(result_long) +
geom_point(aes(reading, value, color = reading_type, group = reading_type)) +
geom_line(aes(reading, value, color = reading_type, group = reading_type)) +
facet_wrap(id ~ .)
result_long <- result %>%
filter(complete.cases(.)) %>%
gather("reading_type", "value", -id, -reading) %>%
> head(result_long)
id reading reading_type value
1 1 v1 systolic 116
2 1 v2 systolic 121
3 1 v3 systolic 105
4 2 v1 systolic 164
5 2 v2 systolic 171
6 2 v3 systolic 155
result <- data %>%
gather("reading", "value", -id) %>%
mutate(value = trimws(value),
value = ifelse(value == "", NA_character_, value)) %>%
arrange(id, reading) %>%
separate(value, c("systolic", "diastolic"), "/", convert = TRUE)
> head(result)
id reading systolic diastolic
1 1 v1 116 77
2 1 v2 121 68
3 1 v3 105 76
4 2 v1 164 67
5 2 v2 171 79
6 2 v3 155 68
Je vois où vous allez, mais je ne pense pas que ce serait logique ici. Dans la trame de données d'origine, chaque ligne est un individu, avec plusieurs lectures à des moments différents (non illustrés). Il sera simple de voir comment ces lectures progressent ou si elles répondent à certains critères médicaux si elles sont dans des colonnes séparées. L'individu est l'unité d'analyse et il est plus logique d'avoir toutes ses lectures dans la même ligne.
Je vois que la réponse de quelqu'un vient d'être acceptée, mais je vais quand même publier la mienne. Si vous modifiez votre code de manière minimale, voici une solution:
for (i in 1:3) {
blPr <- blPr %>%
separate(paste0('v', i), c(paste0('v', i, '_sys'), paste0('v', i, '_dias')), sep = ' / ', remove = F)
}
Une brève explication pour (espérons-le) vous aider à comprendre pourquoi votre code n'a pas fonctionné:
vous pouvez utiliser des noms de variables non entre guillemets (c'est-à-dire des colonnes) comme arguments inverses, mais ceux-ci ne sont pas transparents du point de vue référentiel. Cela signifie que votre code recherche une colonne littéralement nommée v à l'intérieur de blPr et n'en trouve évidemment pas. Parfois, mais pour autant que je sache pas toujours, les verbes tidyverse (par exemple séparés ) acceptent des chaînes avec des noms de colonnes pour signifier ces colonnes - la fonctionnalité que j'ai utilisée dans le code ci-dessus (notez que ' v ' est une chaîne). Pour plus d'informations, vous pouvez consulter les évaluations soignées, les quasi-citations et autres.
Ce code est beaucoup plus clair pour moi et merci aussi pour votre explication - cela a beaucoup de sens pour moi. Pour les autres qui peuvent le consulter, j'ai voté pour la bonne réponse. Mes excuses pour toute maladresse - je suis nouveau sur StackOverflow.
Salut @David, quelle est la sortie attendue pour votre exemple?
étrange: les éléments de l'en-tête sont séparés par
,et les parties des données par/Je veux avoir des variables séparées pour les lectures systolique et diastolique, qui sont maintenant séparées par une barre oblique dans une seule variable. Toutes les variables sont séparées par des virgules dans le fichier csv.
Salut @David, bienvenue sur StackOverflow! Pouvez-vous faire
dput (head (df))(oùdfest le nom de votre dataframe) et l'ajouter à votre question en utilisant leeditoption en bas à gauche de votre question? Si vous pouvez le faire et ajouter votre résultat attendu, cela vous aidera à obtenir une réponse plus rapide et pertinente.Quelles lectures souhaitez-vous conserver par ID? Le premier, le dernier, tous?
Tous sont pertinents.