2
votes

Comment puis-je compter le nombre de jours entre un 1 et le 0 suivant

[J'ai joint une photo de ma série et le code pour obtenir la série, comment pourrais-je obtenir le nombre de jours entre un 1 et le suivant 0. Par exemple, le nombre de jours entre le premier 1 et le suivant 0 est de 4 jours (du 1er août au 5 août], le nombre de jours entre le 1 et le 0 suivant est également de 4 jours [du 8 août au 12 août 1

values = [1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1]
      
dates =['2019-08-01', '2019-08-02', '2019-08-05', '2019-08-06',
           '2019-08-07', '2019-08-08', '2019-08-09', '2019-08-12',
           '2019-08-13', '2019-08-14', '2019-08-15', '2019-08-16',
           '2019-08-19', '2019-08-20', '2019-08-21', '2019-08-22',
           '2019-08-23', '2019-08-26', '2019-08-27', '2019-08-28',
           '2019-08-29', '2019-08-30']

pd.Series(values, index = dates)


2 commentaires

bienvenue à SO! Veuillez coller les données directement dans la question et mettre en forme sous forme de code. Facilite la copie et la réplication


Ce n'est pas votre question, mais veuillez jeter un œil à la réponse acceptée pour stackoverflow.com/questions/57431667/… . (Il compte le nombre jusqu'à une nouvelle occurrence.)


3 Réponses :


0
votes

Je pense que quelque chose comme ci-dessous devrait fonctionner, commencez par avoir une série avec un index de date:

starts = ds.index[delta == 1]
ends = ds.index[delta == -1]
(ends - starts[:len(ends)]).days

Int64Index([4, 4, 1, 7], dtype='int64')

Ensuite, vous calculez la différence entre des valeurs consécutives:

pd.DataFrame({'value':ds,'delta':delta})


    value   delta
2019-08-01  1   1
2019-08-02  1   0
2019-08-05  0   -1
2019-08-06  0   0
2019-08-07  0   0
2019-08-08  1   1
2019-08-09  1   0
2019-08-12  0   -1
2019-08-13  1   1
2019-08-14  0   -1

Cela ressemble à ceci:

delta = ds - ds.shift(fill_value=ds[0]-1)

Ainsi, les dates de début dont vous avez besoin sont lorsque delta est 1, et le prochain zéro dont vous avez besoin est celui où il est -1.

ds = pd.Series(values, index = pd.to_datetime(dates))

Notez qu'il y a des cas où à la fin de la trame de données, vous avez des 1 mais ils ne basculent pas en 0, donc je les ignore.


5 commentaires

Merci, cela a fonctionné, maintenant je dois faire la même chose pour un autre ensemble de données, mais où les index sont des intergers, avez-vous une idée de la façon de procéder?


lorsque vous créez l'index, vous n'ajoutez pas pd.to_datetime() ? Cela devrait fonctionner si vos index ne sont pas dupliqués.


J'obtiens une erreur concernant la valeur de remplissage devant être scalaire lorsque les index sont des nombres entiers


salut @ VanillaChoco441, je ne peux pas vous aider si je ne vois pas les données. J'ai essayé mon code ci-dessus avec un index qui sont des entiers et cela a fonctionné. Et je suppose que vous devez construire correctement la série pd. De plus, comme vous êtes nouveau dans SO, cela sort un peu du cadre de votre question


J'espère que vous seriez juste envers les utilisateurs qui ont fait de leur mieux pour répondre à votre question, et ne pas déplacer le message d'objectif en posant plus de questions qui sont hors de portée ... ou concernant un autre ensemble de données dans ce cas



1
votes

Vous essayez ceci en utilisant groupby comme itertool.groupby ici. L'extrait 1er index de chaque groupe. Puisque vous devez trouver la différence entre deux groupes, il doit y avoir le même nombre de 1 groupes et 0 groupes, si ce n'est pas le cas, supprimez le dernier groupe.

days = np.diff(vals, axis=1).squeeze()
out = pd.Series(days)
# out

0   4 days
1   4 days
2   1 days
3   7 days
dtype: timedelta64[ns]

Maintenant, nous n'avons pas le même nombre de 1 groupes et 0 groupes, alors abandonnez l'index de groupe. Et faites des morceaux pour la taille 2, c'est-à-dire maintenant, chacun a 1 et 0 index de groupe.

end = None if not len(vals)%2 else -1
vals = vals.iloc[:end].values.reshape((-1, 2))
# vals 
array([['2019-08-01T00:00:00.000000000', '2019-08-05T00:00:00.000000000'],
       ['2019-08-08T00:00:00.000000000', '2019-08-12T00:00:00.000000000'],
       ['2019-08-13T00:00:00.000000000', '2019-08-14T00:00:00.000000000'],
       ['2019-08-16T00:00:00.000000000', '2019-08-23T00:00:00.000000000']],
      dtype='datetime64[ns]')

Maintenant, nous devons trouver la différence en utilisant np.diff .

s = pd.Series(values, index = pd.to_datetime(dates))
g = s.ne(s.shift()).cumsum()
vals = s.groupby(g).apply(lambda x:x.index[0])
# vals
1    2019-08-01
2    2019-08-05
3    2019-08-08
4    2019-08-12
5    2019-08-13
6    2019-08-14
7    2019-08-16
8    2019-08-23
9    2019-08-29
dtype: object


0 commentaires

0
votes

À partir de la création d'une trame de données avec colonne de date composée de dates converties en datetime et colonne val composé de valeurs:

         date  val  dist
0  2019-08-01    1     4
1  2019-08-02    1     3
2  2019-08-05    0     0
3  2019-08-06    0     0
4  2019-08-07    0     0
5  2019-08-08    1     4
6  2019-08-09    1     3
7  2019-08-12    0     0
8  2019-08-13    1     1
9  2019-08-14    0     0
10 2019-08-15    0     0
11 2019-08-16    1     7
12 2019-08-19    1     4
13 2019-08-20    1     3
14 2019-08-21    1     2
15 2019-08-22    1     1
16 2019-08-23    0     0
17 2019-08-26    0     0
18 2019-08-27    0     0
19 2019-08-28    0     0
20 2019-08-29    1     0
21 2019-08-30    1     0

L'idée pour obtenir le résultat est:

  • Obtenez les dates où val == 0 (pour les autres lignes, prenez NaT ).
  • Effectuez un "remplissage à l'envers".
  • Soustrayez la date .
  • À partir du résultat ci-dessus ( timedelta ), obtenez le nombre de jours.
  • Remplissez les valeurs NaT en suspens (le cas échéant) avec 0 (dans votre cas, cela concerne les 2 dernières lignes, qui ne sont suivies d'aucune «ligne 0 »).
  • Enregistrez le résultat dans la colonne dist .

Le code pour le faire est:

df['dist'] = (df.date.where(df.val == 0).bfill(0) - df.date)\
    .dt.days.fillna(0, downcast='infer')

Le résultat est:

df = pd.DataFrame({'date': pd.to_datetime(dates), 'val': values})

(La colonne dist est la distance en jours).

Si vous avez besoin, ne prenez dans le résultat ci-dessus que les lignes avec val! = 0 .


0 commentaires