Разделение данных на подвыборки - PullRequest
1 голос
/ 17 марта 2020

У меня есть огромный набор данных, который содержит координаты частиц. Чтобы разделить данные на тестовые и обучающие наборы, я хочу разделить пространство на множество подпространств; Я сделал это с for-l oop во всех направлениях (x, y, z), но при запуске кода это занимает очень много времени и недостаточно эффективно, особенно для больших наборов данных:

particle_boxes = []


init = 0
final = 50
number_box = 5

for i in range(number_box):

    for j in range(number_box):

        for k in range(number_box):

            index_particle = df_particles['X'].between(init+i*final, final+final*i)&df_particles['Y'].between(init+j*final, final+final*j)&df_particles['Z'].between(init+k*final, final+final*k)


            particle_boxes.append(df_particles[index_particle])

, где init и final определяют размер блока, df_particles содержит каждую координату частицы (x, y, z).

После выполнения этого particle_boxes содержит 125 (число_бокс ^ 3) подпакетов с равным интервалом.

Есть ли способ написать этот код более эффективным?

Спасибо

Ответы [ 3 ]

3 голосов
/ 17 марта 2020

Примечание по эффективности

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

Мне любопытно посмотреть, придет ли кто-нибудь еще что-нибудь на порядок быстрее.

Пример данных

np.random.seed([3, 1415])
df_particles = pd.DataFrame(
    np.random.randint(250, size=(1000, 3)),
    columns=['X', 'Y', 'Z']
)

Решение

Создайте массив a, представляющий ваши границы

a = np.array([50, 100, 150, 200, 250])

Затем используйте searchsorted для создания отдельных размерных ячеек

x_bin = a.searchsorted(df_particles['X'].to_numpy())
y_bin = a.searchsorted(df_particles['Y'].to_numpy())
z_bin = a.searchsorted(df_particles['Z'].to_numpy())

Используйте groupby на трех корзинах. Я использовал хитрость, чтобы получить это в dict

g = dict((*df_particles.groupby([x_bin, y_bin, z_bin]),))

Мы можем видеть первую зону

g[(0, 0, 0)]

      X   Y   Z
30    2  36  47
194   0  34  45
276  46  37  34
364  10  16  21
378   4  15   4
429  12  34  13
645  36  17   5
743  18  36  13
876  46  11  34

и последнюю

g[(4, 4, 4)]

       X    Y    Z
87   223  236  213
125  206  241  249
174  218  247  221
234  222  204  237
298  208  211  225
461  234  204  238
596  209  229  241
731  210  220  242
761  225  215  231
762  206  241  240
840  211  241  238
846  212  242  241
899  249  203  228
970  214  217  232
981  236  216  248
1 голос
/ 17 марта 2020

Вместо нескольких вложенных циклов for рассмотрим один l oop, используя itertools.product. Но, конечно, по возможности избегайте петель, поскольку @piRSquared показывает :

from itertools import product

particle_boxes = []

for i, j, k in product(range(number_box), range(number_box), range(number_box)):

    index_particle  = (df_particles['X'].between(init+i*final, final+final*i) & 
                       df_particles['Y'].between(init+j*final, final+final*j) & 
                       df_particles['Z'].between(init+k*final, final+final*k))

    particle_boxes.append(df_particles[index_particle])

В качестве альтернативы, со списком:

def sub_df(i, j, k)
   index_particle  = (df_particles['X'].between(init+i*final, final+final*i) & 
                      df_particles['Y'].between(init+j*final, final+final*j) & 
                      df_particles['Z'].between(init+k*final, final+final*k))

   return df_particles[index_particle]

particle_boxes = [sub_df(i, j, k) for product(range(number_box), range(number_box), range(number_box))]
0 голосов
/ 17 марта 2020

Посмотрите на функцию train_test_split , доступную в scikit-learn lib.

Я думаю, что это почти та функциональность, которая вам нужна.

Код доступен на Github.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...