Pandas groupby: эффективно извлекайте индексы - PullRequest
0 голосов
/ 01 июля 2018

Я пытаюсь эффективно разделить трехмерное облако точек на несколько 2D плиток / сегментов.

Используя комбинацию функций поиска numpy () и pandas groupby (), я смог отсортировать данные по группам с приятной скоростью.

Например:

import numpy as np
import pandas as pd
import time

scale=100
n_points= 1000000
n_tiles = 1000000

pos = np.empty((n_points,3))
pos[:,0]=np.random.random(n_points)*scale
pos[:,1]=np.random.random(n_points)*scale
pos[:,2]=np.random.random(n_points)

df = pd.DataFrame(pos)

# create bounds for each segment
min_bound,max_bound = 0,scale
x_segment_bounds,xstep = np.linspace(min_bound, max_bound, num=n_tiles**0.5,retstep = True)
x_segment_bounds[0]=x_segment_bounds[0]+xstep/2
y_segment_bounds,ystep = np.linspace(min_bound, max_bound, num=n_tiles**0.5,retstep=True)
y_segment_bounds[0]=y_segment_bounds[0]+ystep/2

# sort into bins
time_grab = time.clock()
bins_x = np.searchsorted(x_segment_bounds, pos[:, 0])
bins_y = np.searchsorted(y_segment_bounds, pos[:, 1])
print("Time for binning: ", time.clock()-time_grab)

df["bins_x"] = bins_x.astype(np.uint16)
df["bins_y"] = bins_y.astype(np.uint16)

# group points
time_grab = time.clock()
segments = df.groupby(['bins_x', 'bins_y'])
print("Time for grouping: ", time.clock()-time_grab)

Производит:

Time for binning:  0.1390
Time for grouping:  0.0043

Проблема, с которой я сталкиваюсь, заключается в эффективном доступе к точечным индексам, которые принадлежат каждой группе в объекте pandas groupby.

Например, цикл по каждой группе очень неэффективен:

segment_indices = []
for i,segment in enumerate(segments):
    segment_indices.append(segment[1].index.values)

занимает ~ 70 секунд.

Я нашел этот метод для извлечения индексов:

segments = df.groupby(['bins_x', 'bins_y']).apply(lambda x: x.index.tolist()) 

, что занимает ~ 10 секунд, однако это все еще сравнительно довольно медленно по сравнению с функциями группирования и группировки. Так как я просто пытаюсь скопировать данные в новый массив или список, а на самом деле не выполняю никаких вычислений, я ожидаю гораздо большей эффективности. Я ожидал бы, что скорости, по крайней мере, аналогичны операциям объединения и группировки.

Мне любопытно, есть ли более эффективный способ извлечения индексов (или любой информации) из объекта groupby? В качестве альтернативы есть ли другой метод для сегментирования / группировки точек, в котором не используются панды, например, альтернатива Numpy или Scipy?

...