2015-07-22 4 views
3

J'ai une trame de données DF, avec trois colonnes et n lignes ci-dessous:R: Fonction Fenêtre

Month Year Default 
1 2015 T 
2 2015 T 
3 2015 F 
4 2015 T 
5 2015 T 
6 2015 T 
7 2015 F 

Je voudrais vérifier s'il y a 3 T dans un rouleau et continuer ensuite imprimer tous l'année et le mois de départ dans un nouveau DF.

J'ai besoin d'obtenir la sortie comme indiqué ci-dessus. La sortie devrait comme:

Month Year 
4 2015 
+1

'rle' sera probablement votre ami –

Répondre

1

Cela pourrait ne pas être la meilleure solution, mais mon premier essai serait - coller ensemble la troisième colonne dans une chaîne - utiliser un regexpr pour trouver toutes les occurences de « TTT » dans ce chaîne, ce qui vous donnera un vecteur. - utiliser ce vecteur pour sous-ensemble de votre dataframe d'origine par ligne, en omettant la dernière colonne

EDIT

maintenant avec le code:

def_str <- paste(as.integer(DF$default), collapse="") 
indices <- unlist(gregexp("111+", def_str)) 
if (!indices[1]==-1){ 
    # if there is no match, indices will be -1 
    DF[indices,-3] 
} 
else { 
    print("someting dramatic about no 3 months rolling T's") 
} 
+1

C'est une très bonne idée, mais nous répondons généralement avec une solution complète avec le code –

+0

Je voulais juste faire des commentaires, mais je ne suis pas autorisé! Donc j'ai dû écrire une réponse. Je suis sûr qu'il y a une bonne raison pour cette règle particulière de stackoverflow, mais je ne la vois pas ... – liesb

2

Voici une tentative en utilisant data.tabledevel version on GH et la nouvelle fonction rleid

library(data.table) # v 1.9.5+ 
setDT(df)[, indx := rleid(Default)] 
df[(Default), if(.N > 2) .SD[1L], by = indx] 
# indx Month Year Default 
# 1: 3  4 2015 TRUE 

Ce que nous faisons essentiellement ici, est de définir un index unique par événements consécutifs dans Default, puis en regardant seulement quand Default == TRUE nous sommes checcking pour chaque groupe si la taille du groupe est supérieure à 2, si c'est le cas, sélectionnez la première instance dans ce groupe.


Une version plus courte (proposée par @Arun) serait

setDT(df)[, if(Default && .N > 2L) .SD[1L], by = .(indx = rleid(Default), Default)] 
+0

juste une autre manière: 'setDT (df) [, si (Default && .N> 2L) .SD [1L ], par =. (indx = rleid (Default), par défaut)] ' – Arun

+0

@Arun ow c'était ma pensée initiale, mais je ne pouvais pas comprendre comment obtenir Default par là et il a continué à retourner une erreur parce qu'elle ne pouvait pas t find 'Default' (n'a pas pensé à l'ajouter à l'instruction' by' aussi) –

1

Une façon de le faire avec RLE dans la base R sans data.table, bien que data.table est un ensemble très doux! Mais parfois les gens veulent juste utiliser la base R sans autres dépendances.

dt <- data.frame(Month = c(1, 2, 3, 4, 5, 6, 7), Year = 2015, Default = c(T, T, F, T, T, T, F)) 

runData <- rle(dt$Default) 

whichThree <- which(runData$lengths == 3 & runData$values) 

idx <- unlist(lapply(whichThree - 1, function(x) sum(runData$lengths[1:x]))) 
idx <- idx + 1 

dt[idx, 1:2]