0
votes

Reforming Pandas Dataframe (startdate, enddate) aux colonnes quotidiennes et horaires

  • Je dispose d'un jeu de données comme ci-dessous contenant des informations sur l'état (en ligne, hors ligne, ...) des appareils: Li>
  • Le nom de la date de date suivant est HistoricalData (juste un échantillon) Li>
    cleandataHeader = ['device_id', 'year', 'month', 'day', 'dow', 'uptimeSec', 'downtimeSec']
    
    def fragmentCollect(daystart, dayend, device):
        maskBigFrag = ((historicaldata['Device_id'] == device) & ((daystart < historicaldata['Start_date']) & (dayend > historicaldata['End_date'])))
        BigFragdf = historicaldata.loc[maskBigFrag]
        BigFragdf['fragment'] = (BigFragdf['End_date'] - BigFragdf['Start_date']).dt.total_seconds()
    
        maskSmallFrag = ((historicaldata['Device_id'] == device) & ((daystart > historicaldata['Start_date']) & (dayend < historicaldata['End_date'])))
        SmallFragdf = historicaldata.loc[maskSmallFrag]
        SmallFragdf['fragment'] = (dayend - daystart).total_seconds()
        SmallFragdf['Start_date'] = daystart.strftime('%Y-%m-%d 00:00:00')
        SmallFragdf['End_date'] = dayend.strftime('%Y-%m-%d 00:00:00')
    
        maskHeadFrag = ((historicaldata['Device_id'] == device) & ((daystart >= historicaldata['Start_date'] ) & (daystart < historicaldata['End_date'] ) & (dayend > historicaldata['End_date'] )))
        HeadFragdf = historicaldata.loc[maskHeadFrag]
        HeadFragdf['fragment'] = (HeadFragdf['End_date'] - daystart).dt.total_seconds()
        HeadFragdf['Start_date'] = daystart.strftime('%Y-%m-%d 00:00:00')
    
        maskTailFrag = ((historicaldata['Device_id'] == device) & ((daystart < historicaldata['Start_date'] ) & (dayend <= historicaldata['End_date'] ) & (dayend > historicaldata['Start_date'] )))
        TailFragdf = historicaldata.loc[maskTailFrag]
        TailFragdf['fragment'] = (dayend - TailFragdf['Start_date']).dt.total_seconds()
        TailFragdf['End_date'] = dayend.strftime('%Y-%m-%d 00:00:00')
    
        frames = [BigFragdf, SmallFragdf, HeadFragdf, TailFragdf]
        result = pd.concat(frames)
        result = result.drop_duplicates()
        return result
    
    def rowClean(row):
        row['Player Name'] = row.name[1]
        row['year'] = row.name[0].year
        row['month'] = row.name[0].month
        row['day'] = row.name[0].day
        row['dow'] = row.name[0].day_name()
        result = fragmentCollect(row.name[0], row.name[0] + timedelta(days=1), row.name[1])
        result = result.to_dict('records')
        uptime = 0
        downtime = 0
        for frag in result:
            if frag['status'] == 'Online':
                uptime += frag['fragment']
            else:
                downtime += frag['fragment']
        row['uptimeSec'] = uptime 
        row['downtimeSec'] = downtime
        return row
    
    def buildTheCleanData(start, end):
        datelist = [start + timedelta(days=x) for x in range((end-start).days + 1)]
        iterables = [datelist,['AUH888', 'SHJ656']
        Index = pd.MultiIndex.from_product(iterables, names=['date', 'Device_id'])
        s = pd.DataFrame(columns = cleandataHeader, index = Index)
        s = s.apply(rowClean, axis=1)
        return s
    
    • La colonne d'état contient quatre statuts (en ligne, hors ligne, échec, lost_communication). LI>
    • Chaque périphérique est des données d'état en streaming avec la date de début et de fin de chaque statut li>
    • Chaque statut pourrait être une période de secondes, minutes, jours ou même mois, il sera donc difficile de visualiser les données quotidiennes ou horaires. Li>
    • Je dois analyser le statut pour indiquer la disponibilité par statut quotidiennement et toutes les horaires pour détecter la fluctuation de statut si elle existe. LI>
    • Mon objectif est de remodeler la date de la date à un nouveau Dataframe quotidien, comme suit: Li> ul> xxx pré>
      • Uptime >> Quand statut Online LI>
      • Downtime >> Lorsque le statut est (hors ligne, échec, perte_communication) li>
      • J'utilise le code suivant, mais c'est un peu lent. Li> ul> xxx pré>
        • Fonction FonctionCollect est mon algorithme pour collecter le fragment de statut pour chaque début, fin, périphérique passé. li>
        • Fonction Rowclean sera appliquée sur chaque ligne de la nouvelle Dataframe multiindex pour remplir les informations (UPTUMESEC, DOWNTIMESEC). LI>
        • Buildthecleandata Fonction utilisée pour construire le nouveau Dataframe de disponibilité propre par jour. Li>
        • Je peux appliquer le même concept si je veux un fichier de données propre de jour par heure. Li>
        • Comme vous pouvez le voir, mon code ci-dessus est très lent. li>
        • Je me demandais s'il y a une construction de Pandas qui traite de nombreuses situations similaires plus rapides. Li> ul> ul>

0 commentaires

3 Réponses :


0
votes

Que pourrait-on faire ici serait d'obtenir d'abord des rangées scindées couvrant à des jours différents pour que chaque rangée appartient à une seule journée. Les rangées à scinder sont celles où la date (jour) est différente pour Start_Date et End_Date. Ensuite, la ligne initiale serait terminée à la fin du premier jour et des lignes supplémentaires seraient préparées pour chaque nouvelle journée dans la plage [start_date, end_date).

Une fois que cela est fait, il devient facile d'ajouter pour chaque rangée. une date, ainsi que les durées de disponibilité et du temps d'arrêt. Après avoir résumé ces durées pour chaque paire Device_ID, date nous obtenons le résultat attendu. P>

code pourrait être: p> xxx pré>

Il donne comme prévu: P >

Device_id  year  month  day        dow  uptimeSec  downtimeSec
  AUH888  2018     10   22     Monday       6034        49564
  AUH888  2018     10   23    Tuesday       1199        85201
  AUH888  2018     10   24  Wednesday          0        86400
  AUH888  2018     10   25   Thursday      56872        29528
  AUH888  2018     10   26     Friday      86400            0
  AUH888  2018     10   27   Saturday      86400            0
  AUH888  2018     10   28     Sunday      86400            0
  AUH888  2018     10   29     Monday      86400            0


3 commentaires

Salut Serge, la fractionnement est vraiment une bonne façon de le faire et c'est vraiment rapide aussi, mais comme je suis nouveau à Pandas, je me suis perdue jours_to_add = (new_days.end_date - new_days.start_date) .dt.floor ('d ') .dt.dadays à la fin J'ai essayé votre code sur mes données d'origine, mais j'ai quelques données manquantes mon code d'origine contient des données de plus de 100 périphériques, mais je ne pense pas que cela fera une différence dans la code.


J'ai essayé ce qui suit remodelé.loc [(Rohaped ['Année'] == 2019) & (Rohaped ['Mois'] == 6) & (Rohaped ["Day '] == 1)] Pour obtenir tous les appareils pour 2019/06/01 et j'ai obtenu seulement 7 appareils de ce jour-là, pouvez-vous s'il vous plaît aider peut-être que j'utilise LOC à Wronge Way.


Je crois que votre code n'a pas considéré que les enregistrements que la durée entre les données de démarrage et la date de fin est plus de 2 jours (il y a quelques records aura une date de début de l'exemple 24/05/2019 12:47:08 et la date de fin est 09/06/2019 16:58)



0
votes

Je suis arrivé à trébucher sur le même problème où je devais calculer quelque chose de similaire mais sur un cadre de 15 minutes au lieu d'une image de 1 jour. J'ai essayé d'appliquer ma solution à votre problème.

1) Comme décrit par Serge Ballesta, il est important de diviser les lignes en unités de temps fixes, dans vos journées de cas. Mon approche consistait à convertir les moments de début et de fin au début et à la durée. P>

J'ai essayé ce code avec un extrait de vos données ajoutées à la fin. P>

data = np.array([[40162,     'AUH888',       1, '2018-10-22 08:33:22', '2018-10-22 08:34:26'], 
 [40163,     'AUH888',       0, '2018-10-22 08:34:26', '2018-10-22 10:15:00'], 
 [40167,     'AUH888',       3, '2018-10-22 10:15:00', '2018-10-23 12:40:01'], 
 [40224,     'AUH888',       0, '2018-10-23 12:40:01', ' 2018-10-23 13:00:00'], 
 [40227,     'AUH888',       3, '2018-10-23 13:00:00', ' 2018-10-25 07:43:30'], 
 [40296,     'AUH888',       0, '2018-10-25 07:43:30', ' 2018-10-25 08:00:00'], 
 [40298,     'AUH888',       3, '2018-10-25 08:00:00', ' 2018-10-25 08:28:38'], 
 [40301,     'AUH888',       0, '2018-10-25 08:28:38', ' 2018-11-05 12:15:00'], 
 [40965,     'AUH888',       3, '2018-11-05 12:15:00', ' 2018-11-07 08:06:58'], 
 [41085,     'AUH888',       0, '2018-11-07 08:06:58', ' 2018-11-12 07:15:00'], 
 [41256,     'AUH888',       3, '2018-11-12 07:15:00', ' 2018-11-12 07:19:29'], 
 [41257,     'AUH888',       0, '2018-11-12 07:19:29', ' 2018-11-15 10:45:00'], 
 [41412,     'AUH888',       3, '2018-11-15 10:45:00', ' 2018-11-17 09:38:42'], 
 [41469,     'AUH888',       0, '2018-11-17 09:38:42', ' 2018-11-19 10:15:00']])
cols = ['History_id', 'Device_id','Status', 'Start_date', 'End_date']
df = pd.DataFrame(data, columns=cols)


2 commentaires

L'enregistrement avec Index 2018-10-24 devrait montrer hors ligne avec 86400 car dans l'enregistrement suivant dans le df d'origine: 40227, 'Auh888', 3, '2018-10-23 13:00:00', ' 2018-10-25 07:43:30 '


Oui tu as raison. Cela ne fonctionne pas dans cette application. Dans ma candidature, ce n'était pas un problème, pour d'autres raisons. Je vais devoir travailler dessus.



0
votes

My Verstion: xxx

sortie: xxx

csv: xxx


0 commentaires