удалить часть массива, если последовательность нанов> 20 подряд - PullRequest
0 голосов
/ 01 июля 2018

Я могу удалить все нан в массиве x numpy и из связанного массива y с маской или

y = y[~np.isnan(x)]
x = x[~np.isnan(x)]

Теперь мне нужно удалять детали только тогда, когда их много (скажем, 20 NaNs подряд). Кто-нибудь знает, как решить эту проблему?

1 Ответ

0 голосов
/ 01 июля 2018

В этом вопросе есть некоторая двусмысленность, но, тем не менее, было бы неплохо ответить на обе версии. Я не уверен, что вы имели в виду, что вам нужно удалить разделы, в которых имеется более 20 последовательных NaN на одномерных данных, или если вы имели в виду, что вам нужно удалить строки из 2D-данных, чтобы было более 20 NaN (где угодно) в ряд. Тай уже ответил Тай, поэтому я отвечу на первый.

Идея здесь состоит в том, чтобы выяснить, какие индексы имеют NaN, а затем сгруппировать эти индексы в полосы, где они происходят последовательно, отфильтровать полосы, которые не являются достаточно длинными, и, наконец, создать маску с оставшимися полосами / индексы (фью).

import numpy as np

# Construct some test data
x = np.arange(150, dtype=np.float)
x[20:50] = np.NaN # remove this streak                                                                                                                                                                      
x[70:80] = np.NaN # keep this streak                                                                                                                                                                        
x[105:140] = np.NaN # remove this streak                                                                                                                                                                    
x[149] = np.NaN # keep this lone soldier                                                                                                                                                                    
print("Original (with long streaks): ", x)

# Calculate streaks, filter out streaks that are too short, apply global mask
nan_spots = np.where(np.isnan(x))
diff = np.diff(nan_spots)[0]
streaks = np.split(nan_spots[0], np.where(diff != 1)[0]+1)
long_streaks = set(np.hstack([streak for streak in streaks if len(streak) > 20]))
mask = [item not in long_streaks for item in range(len(x))]
print("Filtered (without long streaks): ", x[mask])

assert len(x[mask]) == len(x) - (50 - 20) - (140-105)

Выходы:

Original (with long streaks):  [  0.   1.   2.   3.   4.   5.   6.   7.   8.   9.  10.  11.  12.  13.
  14.  15.  16.  17.  18.  19.  nan  nan  nan  nan  nan  nan  nan  nan
  nan  nan  nan  nan  nan  nan  nan  nan  nan  nan  nan  nan  nan  nan
  nan  nan  nan  nan  nan  nan  nan  nan  50.  51.  52.  53.  54.  55.
  56.  57.  58.  59.  60.  61.  62.  63.  64.  65.  66.  67.  68.  69.
  nan  nan  nan  nan  nan  nan  nan  nan  nan  nan  80.  81.  82.  83.
  84.  85.  86.  87.  88.  89.  90.  91.  92.  93.  94.  95.  96.  97.
  98.  99. 100. 101. 102. 103. 104.  nan  nan  nan  nan  nan  nan  nan
  nan  nan  nan  nan  nan  nan  nan  nan  nan  nan  nan  nan  nan  nan
  nan  nan  nan  nan  nan  nan  nan  nan  nan  nan  nan  nan  nan  nan
 140. 141. 142. 143. 144. 145. 146. 147. 148.  nan]

Filtered (without long streaks):  [  0.   1.   2.   3.   4.   5.   6.   7.   8.   9.  10.  11.  12.  13.
  14.  15.  16.  17.  18.  19.  50.  51.  52.  53.  54.  55.  56.  57.
  58.  59.  60.  61.  62.  63.  64.  65.  66.  67.  68.  69.  nan  nan
  nan  nan  nan  nan  nan  nan  nan  nan  80.  81.  82.  83.  84.  85.
  86.  87.  88.  89.  90.  91.  92.  93.  94.  95.  96.  97.  98.  99.
 100. 101. 102. 103. 104. 140. 141. 142. 143. 144. 145. 146. 147. 148.
  nan]

И если нужно, просто примените ту же маску к y (т.е. y = y[mask]). Вы можете обобщить это для многомерных данных, но вам нужно будет выбрать ось, по которой вы хотите найти последовательные NaN.

...