Требуется справка по Numpy: как использовать логические значения для вычисления диапазонов и сложения значений внутри диапазонов? - PullRequest
0 голосов
/ 13 октября 2018

У меня есть матрица Nx2, такая как:

M = [[10, 1000],
 [11, 200],
 [15, 800],
 [20, 5000],
 [28, 100],
 [32, 3000],
 [35, 3500],
 [38, 100],
 [50, 5000],
 [51, 100],
 [55, 2000],
 [58, 3000],
 [66, 4000],
 [90, 5000]]

Мне нужно создать матрицу Nx3, которая отражает отношение строк из первой матрицы следующим образом:

Используйте правый столбец для определения кандидатов на границы диапазона. Условие имеет значение> = 1000

Это условие применимо к матрице:

[[10, 1000],
 [20, 5000],
 [32, 3000],
 [35, 3500],
 [50, 5000],
 [55, 2000],
 [58, 3000],
 [66, 4000],
 [90, 5000],]

До сих пор я придумал "M [M[:, 1]> = 1000] "который работает.Для этой новой матрицы я хочу теперь проверить точки в первом столбце, к которым относится расстояние до следующей точки <= 10, и использовать их в качестве границ диапазона. </p>

То, что я до сих пор придумал: np.diff(M [:, 0]) <= 10, что возвращает: </p>

[True, False, True, False, True, True, True, False]

Вот где я застрял.Я хочу использовать это условие для определения нижней и верхней границы диапазона.Например:

[[10, 1000], #<- Range 1 start
 [20, 5000], #<- Range 1 end (as 32 would be 12 points away)
 [32, 3000], #<- Range 2 start
 [35, 3500], #<- Range 2 end
 [50, 5000], #<- Range 3 start
 [55, 2000], #<- Range 3 cont (as 55 is only 5 points away)
 [58, 3000], #<- Range 3 cont
 [66, 4000], #<- Range 3 end
 [90, 5000]] #<- Range 4 start and end (as there is no point +-10)

Наконец, возвращаясь к самой первой матрице, я хочу добавить значения в правом столбце вместе для каждого диапазона в пределах (включая) границы.

ИтакУ меня есть четыре диапазона, которые определяют начало и конец границ.

  • Диапазон 1: начало 10, конец 20
  • Диапазон 2: начало 32, конец 35
  • Диапазон 3: начало 50, конец 66
  • Диапазон 4: начало 90, конец 90

Получившаяся матрица будет выглядеть следующим образом, где столбец 0 - начальная граница, столбец 1 -конец границы и столбец 2 добавленные значения из матрицы M из правого столбца между началом и концом.

[[10, 20, 7000], # 7000 = 1000+200+800+5000
 [32, 35, 6500], # 6500 = 3000+3500
 [50, 66, 14100], # 14100 = 5000+100+2000+3000+4000
 [90, 90, 5000]] # 5000 = just 5000 as upper=lower boundary

Я застрял на втором шаге, после того как я получил значения true / false для границ диапазона.Но как мне создать диапазоны из логических значений, а затем как сложить значения в этих диапазонах, мне неясно.Буду признателен за любые предложения.Кроме того, я не уверен в своем подходе, может быть, есть лучший способ перейти от первой к последней матрице, может быть, пропуская один шаг ??

РЕДАКТИРОВАТЬ

Итак, я пришелнемного дальше со средним шагом, и теперь я могу вернуть начальное и конечное значения диапазона:

start_diffs = np.diff(M[:,0]) > 10
start_indexes = np.insert(start_diffs, 0, True)

end_diffs = np.diff(M[:,0]) > 10
end_indexes = np.insert(end_diffs, -1, True)

start_values = M[:,0][start_indexes]
end_values = M[:,0][end_indexes]

print(np.array([start_values, end_values]).T)

Возвращает:

[[10 20]
 [32 35]
 [50 66]
 [90 90]]

Чего не хватает, так или иначе используя эти диапазоныТеперь вычислим суммы из матрицы М в правом столбце.

1 Ответ

0 голосов
/ 13 октября 2018

Если вы открыты для использования pandas, вот решение, которое кажется несколько обдуманным, но работает:

# Initial array
M = np.array([[10, 1000],
              [11, 200],
              [15, 800],
              [20, 5000],
              [28, 100],
              [32, 3000],
              [35, 3500],
              [38, 100],
              [50, 5000],
              [51, 100],
              [55, 2000],
              [58, 3000],
              [66, 4000],
              [90, 5000]])

# Build a DataFrame with default integer index and column labels
df = pd.DataFrame(M)

# Get a subset of rows that represent potential interval edges
subset = df[df[1] >= 1000].copy()

# If a row is the first row in a new range, flag it with 1.
# Then cumulatively sum these 1s. This labels each row with a 
# unique integer, one per range
subset[2] = (subset[0].diff() > 10).astype(int).cumsum()

# Get the start and end values of each range
edges = subset.groupby(2).agg({0: ['first', 'last']})
edges
          0     
  first last
2           
0    10   20
1    32   35
2    50   66
3    90   90

# Build a pandas IntervalIndex out of these interval edges
tups = list(edges.itertuples(index=False, name=None))
idx = pd.IntervalIndex.from_tuples(tups, closed='both')

# Build a Series that maps each interval to a unique range number
mapping = pd.Series(range(len(idx)), index=idx)

# Apply this mapping to create a new column of the original df
df[2] = [mapping.loc[i] if idx.contains(i) else None for i in df[0]]
df
     0     1    2
0   10  1000  0.0
1   11   200  0.0
2   15   800  0.0
3   20  5000  0.0
4   28   100  NaN
5   32  3000  1.0
6   35  3500  1.0
7   38   100  NaN
8   50  5000  2.0
9   51   100  2.0
10  55  2000  2.0
11  58  3000  2.0
12  66  4000  2.0
13  90  5000  3.0

# Group by this new column, get edges of each interval, 
# sum values, and get the underlying numpy array
df.groupby(2).agg({0: ['first', 'last'], 1: 'sum'}).values
array([[   10,    20,  7000],
       [   32,    35,  6500],
       [   50,    66, 14100],
       [   90,    90,  5000]])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...