Как создать DataFrame Pandas из отдельных массивов 1D Numpy без копирования - PullRequest
0 голосов
/ 04 марта 2019

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

Я хочу создатьDataFrame из отдельных массивов 1D Numpy для каждого столбца.Я попробовал очевидное DataFrame({"col": nparray, "col": nparray}), но это отображается вверху моего профиля, поэтому он должен делать что-то очень медленное.

Насколько я понимаю, Pandas DataFrames реализованы на чистом Python, где каждый столбецподдерживается массивом Numpy, поэтому я думаю, что есть эффективный способ сделать это.

Что я на самом деле пытаюсь сделать, так это эффективно заполнить DataFrame из Cython.У Cython есть представления памяти, которые обеспечивают эффективный доступ к массивам Numpy.Поэтому моя стратегия состоит в том, чтобы выделить массив Numpy, заполнить его данными, а затем поместить в DataFrame.

Обратное работает довольно хорошо, создавая представление памяти из DataFrame Pandas.Так что, если есть способ предварительно выделить весь DataFrame, а затем просто передать столбцы в Cython, это также допустимо.

cdef int32_t[:] data_in = df['data_in'].to_numpy(dtype="int32")

Раздел профиля моего кода выглядит следующим образом, где весь кодdo полностью затмевается созданием DataFrame в конце.

         1100546 function calls (1086282 primitive calls) in 4.345 seconds

   Ordered by: cumulative time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    4.345    4.345 profile:0(<code object <module> at 0x7f4e693d1c90, file "test.py", line 1>)
    445/1    0.029    0.000    4.344    4.344 :0(exec)
        1    0.006    0.006    4.344    4.344 test.py:1(<module>)
     1000    0.029    0.000    2.678    0.003 :0(run_df)
     1001    0.017    0.000    2.551    0.003 frame.py:378(__init__)
     1001    0.018    0.000    2.522    0.003 construction.py:170(init_dict)

Соответствующий код:

def run_df(self, df):
    cdef int arx_rows = len(df)
    cdef int arx_idx

    cdef int32_t[:] data_in = df['data_in'].to_numpy(dtype="int32")

    data_out_np = np.zeros(arx_rows, dtype="int32")
    cdef int32_t[:] data_out = data_out_np

    for arx_idx in range(arx_rows):
        self.cpp_sec_par.run(data_in[arx_idx],data_out[arx_idx],)

    return pd.DataFrame({
        'data_out': data_out_np,
    })

Ответы [ 2 ]

0 голосов
/ 26 августа 2019
DataFrame({"col": nparray, "col": nparray})

Это работает, если вы попробуете list (nparray).Вот общий пример:

import numpy as np
import pandas as pd

alpha = np.array([1, 2, 3])
beta = np.array([4, 5, 6])
gamma = np.array([7, 8, 9])

dict = {"Alpha" : list(alpha), "Beta" : list(beta), "Gamma":list(gamma)}

data_frame = pd.DataFrame(dict)
print(data_frame)
0 голосов
/ 05 мая 2019

Могу ли я предложить добавить столбцы один за другим.Это может помочь с эффективностью.Например,

import numpy as np
import pandas as pd

df = pd.DataFrame()

col1 = np.array([1, 2, 3])
col2 = np.array([4, 5, 6])

df['col1'] = col1
df['col2'] = col2
>>> df
   col1  col2
0     1     4
1     2     5
2     3     6
...