J'ai un bloc de données comme indiqué ci-dessous
sorted <- test_df %>% arrange(date_1,group_by = subject_id) #Am I right in sorts the dates within group? test_df$month = month(test_df$date_1) #get the month test_df$day = day(test_df$date_1) #get the year filter(test_df, month==12 and day == 31) # doesn't work here
Ce que je voudrais faire, c'est
Organisez les dates par ordre croissant pour chaque sujet (triez par ordre croissant dans les groupes)
Supprimez les enregistrements de date pour chaque sujet en fonction des critères ci-dessous (l'année n'a pas d'importance):
2a. supprimer uniquement les enregistrements du 31 décembre si le premier enregistrement du sujet est le 1er janvier ex: subject_id = 1
2b. supprimer uniquement les enregistrements du 1er janvier si le premier enregistrement du sujet est le 31 décembre ex: subject_id = 2
2c. supprimer uniquement les enregistrements du 31 décembre si le sujet a à la fois le 31 décembre et le 1er janvier dans ses autres enregistrements (c'est-à-dire du 2ème enregistrement jusqu'à la fin de ses enregistrements) ex: subject_id = 3
J'essayais ce qui suit
test_df <- data.frame("subject_id" = c(1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3), "date_1" = c("01/01/2003", "12/31/2007", "12/30/2008", "12/31/2005", "01/01/2007", "01/01/2013", "12/31/2008", "03/04/2006", "12/31/2009", "01/01/2015", "01/01/2009"))
Pouvez-vous m'aider comment puis-je filtrer les enregistrements en fonction de mes critères?
Je m'attends à ce que ma sortie soit comme ci-dessous
3 Réponses :
Ce n'est pas le plus joli code que j'ai jamais écrit, mais ça marche. J'ai supposé que les filtres étaient exécutés en séquence; sinon, les deuxième et troisième filtres éliminent tout le sujet 2.
test_df %>% mutate(date_1 = as.Date(as.character(date_1), format = "%m/%d/%Y"), month = as.numeric(format(date_1, "%m")), day = as.numeric(format(date_1, "%d"))) %>% group_by(subject_id) %>% arrange(date_1) %>% filter(!(rep(month[1] == 1 & day[1] == 1, n()) & month == 12 & day == 31)) %>% filter(!(rep(month[1] == 12 & day[1] == 31, n()) & month == 1 & day == 1)) %>% filter(!(rep(sum(month[-1] == 1 & day[-1] == 1) > 0 & sum(month[-1] == 12 & day[-1] == 31) > 0, n()) & month == 12 & day == 31)) %>% ungroup() %>% arrange(subject_id, date_1) subject_id date_1 month day <dbl> <date> <dbl> <dbl> 1 1 2003-01-01 1 1 2 1 2008-12-30 12 30 3 2 2005-12-31 12 31 4 2 2008-12-31 12 31 5 3 2006-03-04 3 4 6 3 2009-01-01 1 1 7 3 2015-01-01 1 1
# A tibble: 7 x 2 subject_id date_1 <dbl> <date> 1 1 2003-01-01 2 1 2008-12-30 3 2 2005-12-31 4 2 2008-12-31 5 3 2006-03-04 6 3 2015-01-01 7 3 2009-01-01
Puis-je savoir pourquoi obtenez-vous last_date pour chaque sujet? car 12-31
pourrait également être au milieu en fonction de l'ordre des dates (les années pourraient faire une différence) comme pour subject = 1
Une autre question: pourquoi excluons-nous le premier enregistrement de la trame de données pour vérifier has_both
? all (c ("01-01", "12-31")% in% tail (without_year, -1))
@The Great car c'est le mois-jour du dernier rendez-vous en groupe. J'ai traduit record = row
si la définition de l'enregistrement pour vous est différente, fournissez cette définition.
IIUC, si vous essayez d'obtenir le mois-jour de la dernière date dans le groupe, puis-je vérifier comment il est utilisé plus loin dans le code? Qu'essayons-nous de faire avec la dernière date
?
@The Great for 1st filtering I need to know month-day of first row in group. Similaire pour le deuxième filtrage, j'ai besoin de connaître le dernier mois-jour en groupe. Pour le troisième filtrage, j'ai besoin de savoir s'il y a "01-01" et "31-12" comme mois-jour avec le groupe (à l'exclusion de la première ligne).
Ici dans le 2ème filtre, filter (! (First_date == "12-31" & without_year == "01-01"))
, je vois que vous avez déjà utilisé 12-31
n'est-ce pas? Nous n'utilisons donc pas vraiment la variable last_date
ici. Ai-je bien compris?
Ce que j'essaie de dire, c'est que la variable last_date
n'est utilisée nulle part dans le code pour un traitement ultérieur. Ai-je raison?
@The Great Votre propre deuxième condition de filtrage dit: si la première date (sans année) dans le groupe est "12-31", supprimez toutes les lignes du groupe qui ont la date (sans année) "01-01". C'est exactement ce que fait le deuxième filtrage.
@The Great vous avez tout à fait raison à ce sujet, il semble que je n'utilise pas du tout last_date
, donc c'est redondant.
Merci d'avoir clarifié mes doutes. Très appréciée
continuons cette discussion dans le chat .
Essayez avec date_1 = lubridate :: dmy_hm (date_1)
dans la première mutation.
Salut @det - une petite question. Lorsque vous utilisez arrange ()
dans le code, puis-je savoir comment il trie par colonne date_1
sans mentionner explicitement date_1
dans arrange (date_1)
? Pouvez-vous m'aider avec ça s'il vous plaît?
Vous pouvez peut-être aussi essayer une solution de base avec un peu de lubrifiant:
# split as list listed <- split(test_df, test_df$subject_id) # order each df: requested and fundamental for the function listed <- lapply(listed, function(df){df[order(df$date_1),]}) # here the function: it's a nested if else statement on the field filtering <- function(x){if (head(x,1)$cntrl == "11") { x[x$cntrl != '1231', ] } else if (head(x,1)$cntrl == "1231") { x[x$cntrl != '11', ] } else if ( "11" %in% tail(x,nrow(x)-1)$cntrl & "1231" %in% tail(x,nrow(x)-1)$cntrl) { x[x$cntrl != '1231', ] } else(x)} # lapply it! listed <- lapply(listed, function(x)filtering(x)) # now as a dataframe, removing the useless column: res <- do.call(rbind, listed)[,-3] # lastly you can rename the rownames rownames(res) <- 1:nrow(res) res subject_id date_1 1 1 2003-01-01 2 1 2008-12-30 3 2 2005-12-31 4 2 2008-12-31 5 3 2006-03-04 6 3 2009-01-01 7 3 2015-01-01
Maintenant, l'idée est de diviser votre df dans une liste par groupe subject_id
, puis lapply
une fonction qui filtre en utilisant votre condition:
library(lubridate) # put date_1 as date test_df$date_1 <- lubridate::mdy(test_df$date_1) # create the field that's going to be the filter test_df$cntrl <- paste0(month(test_df$date_1),day(test_df$date_1))
que doit faire
group_by =
dansarrange
? Voulez-vous direarrange (date_1)%>% group_by (subject_id)
? (Et non, l'arrangement se fait quel que soit le groupe (essayezmtcars%>% group_by (cyl)%>% arrange (mpg)%>% print (n = 99)
et voyez qu'il y a un8
au milieu de6
s).Oui, je voulais dire
arrange (date_1)%>% group_by (subject_id)