2 votes

Analyse du tableau avec des séries de binaires pour sélectionner un élément de groupe plus grand

J'ai un tableau comme suit (beaucoup plus long):

#    temps    binaire    fréquence

0     2.1      0         0.65
1     3.2      1         0.72
2     5.8      0         0.64
3     7.1      0         0.63
4     9.5      1         0.72
5     14.1     1         0.74
6     21.5     0         0.62
7     27.3     0         0.61
8     29.5     1         1.00
9     32.1     1         1.12
10    35.5     1         0.99

Je veux collecter tous les temps correspondants uniquement à binaire == 1 et, parmi les petits groupes, ceux dont la valeur correspondante de fréquence est plus élevée. Dans le tableau ci-dessus, cela donnerait :

temps = 3.2, 14.1, 32.1

Je ne suis pas sûr de comment aborder la séquentialité du tableau en premier lieu, puis comment comparer les valeurs entre elles en ne renvoyant que le temps correspondant (et non, par exemple, la fréquence la plus élevée). Le temps cache une périodicité, je préférerais donc éviter de construire un autre tableau avec uniquement des éléments binaire == 1.

Ayant mes tableaux temps, binaire et fréquence, je peux isoler les éléments pertinents en :

condition = (binaire == 1)
temps1 = temps[condition]
fréquence1 = fréquence[condition]

mais je ne sais pas comment procéder pour isoler les différentes séquences. Quelles sont les fonctions utiles que je peux utiliser ?

2voto

Bill Bell Points 1357

Je ne sais pas s'il existe des fonctions astucieuses à utiliser pour cela. Voici un code qui fera le travail. Veuillez noter que j'ai supprimé les en-têtes de votre fichier.

binary est soit zéro soit un, en fonction de savoir si les autres valeurs des lignes doivent être incluses dans un groupe. Initialement, in_group est défini sur False pour indiquer qu'aucun groupe n'a commencé. Au fur et à mesure que les lignes sont lues, lorsque binary est zéro, si le code a été en train de lire les lignes pour un groupe et, par conséquent, que in_group est True, in_group est défini sur False car maintenant qu'un zéro a été rencontré, ce groupe est arrivé à sa fin. Puisque le traitement du groupe est terminé, il est temps d'afficher les résultats pour celui-ci. Au fur et à mesure que les lignes sont lues, lorsque binary est un, si in_group est True, alors le code a déjà commencé à traiter les lignes pour un groupe et le code vérifie si la nouvelle frequency est supérieure à ce qui a été vu auparavant. Si c'est le cas, il met à jour à la fois rep_time et rep_frequency. Si in_group est False, alors c'est la première ligne d'un nouveau groupe et in_group est défini sur True et les valeurs initiales de rep_time et rep_frequency sont définies.

with open('pyser.txt') as pyser:
    in_group = False
    for line in pyser:
        _, time, binary, frequency = [float(_) for _ in line.rstrip().split()]
        if binary == 0:
            if in_group:
                in_group = False
                print (rep_time)
        else:
            if in_group:
                if frequency > rep_frequency:
                    rep_time, rep_frequency = time, frequency 
            else:
                in_group = True
                rep_time, rep_frequency = time, frequency 
if in_group:
    print (rep_time)

Résultat :

3.2
14.1
32.1

Édition : Il semble que nous utilisions des définitions différentes du problème.

échantillon

Dans le premier groupe, nous sommes d'accord. Mais, dans le deuxième groupe, l'amplitude maximale est d'environ 4,07E-01, ce qui correspond à un temps d'environ 5,4740E+04.

J'ai également écrit du code en Pandas :

>>> import pandas as pd
>>> df = pd.read_csv('Gyd9P1rb.txt', sep='\s+', skiprows=2, header=None, names='Row TSTOP PSRTIME DETECTED FDOTMAX AMPLITUDE AMPLITUDE_ERR'.split())
>>> del df['Row']
>>> del df['TSTOP']
>>> del df['FDOTMAX']
>>> del df['AMPLITUDE_ERR']
>>> groupes = []
>>> in_group = False
>>> numéro_groupe = 1
>>> for b in df['DETECTED']:
...     if b:
...         if not in_group:
...             numéro_groupe +=1
...             in_group = True
...         groupes.append(numéro_groupe)
...     else:
...         groupes.append(0)
...         in_group = False
... 

>>> df['groupes'] = pd.Series(groupes, index=df.index)
>>> df.head()
        PSRTIME  DETECTED  AMPLITUDE  groups
0  54695.471283         1   0.466410       2
1  54698.532412         1   0.389607       2
2  54701.520814         1   0.252858       2
3  54704.557583         0   0.103460       0
4  54707.557563         0   0.088215       0
>>> gb = df.groupby(by=df['groups'])
>>> def f(x):
...     the_max = x['AMPLITUDE'].idxmax()
...     print ( x['groups'][the_max], x['PSRTIME'][the_max])
... 
>>> gb.apply(f)
0 58064.3656376
0 58064.3656376
2 54695.4712834
3 54740.4917137
4 54788.477571
5 54836.472922
6 54881.4605511
7 54926.4664883
8 54971.4932866
9 55019.5021472
10 55064.5029133
11 55109.4948108
12 55154.414381
13 55202.488766
14 55247.4721132
15 55292.5301332
16 55340.4728542
17 55385.5229596
18 55430.5332147
19 55478.4812671
20 55523.4894451
21 55568.4626766
22 55616.4630348
23 55661.4969604
24 55709.4504634
25 55754.4711994
26 55799.4736923
27 55844.5050404
28 55892.4699313
29 55937.4721754
30 55985.4677572
31 56030.5119765
32 56075.5517149
33 56168.4447074
34 56213.507484
35 56306.5133063
36 56351.4943058
37 56396.579122
38 56441.5683651
39 56489.5321173
40 56534.4838082
41 56582.469025
42 56627.4135202
43 56672.4926625
44 56720.582296
45 56768.5232469
46 56813.4997925
47 56858.3890558
48 56903.5182596
49 56951.4892721
50 56996.5787435
51 57086.3948136
52 57179.5421833
53 57272.5059448
54 57362.452523
55 57635.5013047
56 57728.4925251
57 57773.5235416
58 57821.5390364
59 57866.5205882
60 57911.5590132
61 57956.5699637
62 58001.4331976
Empty DataFrame
Columns: []
Index: []

Les résultats des deux méthodes sont les mêmes, sauf pour des différences de précision dans la présentation.

J'ai également créé un petit ensemble de données qui donnerait des résultats facilement calculables. Le voici. Le programme original a fonctionné correctement.

0 -1 0 -1
1 0 1 2
2 -1 0 -1
3 -1 0 -1
4 0 1 0
5 1 1 1
6 -1 0 -1
7 -1 0 -1
8 -1 0 -1
9 0 1 4
10 1 1 3
11 2 1 2
12 -1 0 -1
13 -1 0 -1
14 -1 0 -1
15 -1 0 -1
16 0 1 0
17 1 1 1
18 2 1 2
19 3 1 3
20 -1 0 -1
21 -1 0 -1
22 -1 0 -1
23 -1 0 -1
24 -1 0 -1
25 0 1 6
26 1 1 5
27 2 1 4
28 3 1 3
29 4 1 2
30 -1 0 -1
31 -1 0 -1
32 -1 0 -1
33 -1 0 -1
34 -1 0 -1
35 -1 0 -1
36 0 1 0
37 1 1 1
38 2 1 2
39 3 1 3
40 4 1 4
41 5 1 5
41 -1 0 -1
41 -1 0 -1

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X