3
votes

Étirez un tableau et remplissez nan

J'ai un tableau numpy 1-d de longueur n, et je veux l'étirer à m (n Par exemple:

>>> def stretch(x,to,fill=np.nan):
...     step = to/len(x)
...     output = np.repeat(fill,to)
...     foreign = np.arange(0,to,step).round().astype(int)
...     output[foreign] = x
...     return output

>>> arr = np.random.rand(6553)
>>> stretch(arr,6622)

  File "<ipython-input-216-0202bc39278e>", line 2, in <module>
    stretch(arr,6622)

  File "<ipython-input-211-177ee8bc10a7>", line 9, in stretch
    output[foreign] = x

ValueError: shape mismatch: value array of shape (6553,) could not be broadcast to indexing result of shape (6554,)


2 commentaires

Quelle est la logique derrière l'ajout de NaN? Comment sont-ils positionnés?


«Systématiquement» l'explique, en d'autres termes, régulièrement espacé (autant que possible). Je vais gérer les NaN de différentes manières, ce qui est hors sujet pour cette question.


4 Réponses :


0
votes

Vous pouvez utiliser resize pour redimensionner le tableau.

Une fois qu'il est redimensionné, vous pouvez appliquer la logique appropriée pour réorganiser le contenu.

Vérifiez le lien ci-dessous: https://docs.scipy.org/doc/ numpy / reference / generated / numpy.ndarray.resize.html


1 commentaires

Le redimensionnement met des zéros à la fin, alors comment vais-je le séparer des autres zéros (possibles)? Quelle est la bonne façon d'utiliser le redimensionnement?



1
votes

Cette approche place les éléments non-nan aux limites, laissant les valeurs nan au centre, bien qu'elle n'espace pas uniformément les valeurs nan .

In [104]: stretch(arr, stretch_len)   
Out[104]: array([ 4.,  5.,  1., nan, nan,  2.,  6.,  8.])

In [105]: arr = [4, 5, 1, 2, 6, 8, 9]    

In [106]: stretch(arr, stretch_len)  
Out[106]: array([ 4.,  5.,  1., nan,  2.,  6.,  8.,  9.])

In [107]: stretch(arr, 9)  
Out[107]: array([ 4.,  5.,  1., nan, nan,  2.,  6.,  8.,  9.])

Voici quelques cas de test que j'ai testés:

Cas de test:

arr = [4,5,1,2,6,8]   
stretch_len = 8    

def stretch(arr, stretch_len):
    stretched_arr = np.empty(stretch_len)   
    stretched_arr.fill(np.nan)
    arr_len = len(arr)

    if arr_len % 2 == 0:
        mid = int(arr_len/2)
        stretched_arr[:mid] = arr[:mid]
        stretched_arr[-mid:] = arr[-mid:]
    else:
        mid = int(np.floor(arr_len/2))
        stretched_arr[:mid] = arr[:mid]
        stretched_arr[-mid-1:] = arr[-mid-1:]

    return stretched_arr


1 commentaires

Deux nans consécutifs ne satisfont pas à la condition d'être régulièrement espacés. Je m'attendrais à au moins 2 échantillons entre eux.



2
votes

Utilisation de roundrobin de itertools Recettes :

from itertools import cycle, islice

def roundrobin(*iterables):
    "roundrobin('ABC', 'D', 'EF') --> A D E B F C"
    # Recipe credited to George Sakkis
    pending = len(iterables)
    nexts = cycle(iter(it).__next__ for it in iterables)
    while pending:
        try:
            for next in nexts:
                yield next()
        except StopIteration:
            pending -= 1
            nexts = cycle(islice(nexts, pending))

def stretch(x, to, fill=np.nan):
    n_gaps = to - len(x)
    return np.hstack([*roundrobin(np.array_split(x, n_gaps+1), np.repeat(fill, n_gaps))])

arr = [4,5,1,2,6,8]
stretch(arr, 8)
# array([ 4.,  5., nan,  1.,  2., nan,  6.,  8.])

arr2 = np.random.rand(655)
stretched_arr2 = stretch(arr,662)
np.diff(np.argwhere(np.isnan(stretched_arr2)), axis=0)
# nans are evenly spaced    
array([[83],
       [83],
       [83],
       [83],
       [83],
       [83]])

Logique derrière

n_gaps : calcule le nombre de lacunes à combler (longueur souhaitée - longueur actuelle)

np_array_split : avec n_gaps + 1 , il divise le tableau d'entrée en la même longueur que possible

roundrobin : puisque np_array_split génère un tableau de plus que les vides, roundrobin-ing (c'est-à-dire alternativement itérer) accorde que np.nan n'est jamais à l'une ou l'autre extrémité du résultat .


0 commentaires

1
votes

Bien que Chris ait résolu le problème, j'ai trouvé une réponse plus courte, qui peut être utile,

>>> aa[:5]
array([0.78581616, 0.1630689 , 0.52039993,        nan, 0.89844404])
>>> aa[-5:]
array([0.7063653 ,        nan, 0.2022172 , 0.94604503, 0.91201897])


0 commentaires