Преобразование 2D numpy.ndarray в pandas.DataFrame

#python-2.7 #pandas #multidimensional-array

#python-2.7 #pandas #многомерный массив

Вопрос:

У меня довольно большой numpy.ndarray . Это в основном массив массивов. Я хочу преобразовать его в pandas.DataFrame . То, что я хочу сделать, находится в приведенном ниже коде

 from pandas import DataFrame

cache1 = DataFrame([{'id1': 'ABC1234'}, {'id1': 'NCMN7838'}])
cache2 = DataFrame([{'id2': 3276827}, {'id2': 98567498}, {'id2': 38472837}])

ndarr = [[4.3, 5.6, 6.7], [3.2, 4.5, 2.1]]
arr = []
for idx, i in enumerate(ndarr):
    id1 = cache1.ix[idx].id1
    for idx2, val in enumerate(i):
        id2 = cache2.ix[idx2].id2
        if val > 0:
            arr.append(dict(id1=id1, id2=id2, value=val))
df = DataFrame(arr)
print(df.head())
 

Я сопоставляю индекс внешнего массива и внутреннего массива с индексом из двух DataFrame s, чтобы получить определенные идентификаторы.
cache1 и cache2 есть pandas.DataFrame . У каждого есть ~100k строки.

Это занимает действительно много времени, например, несколько часов. Есть ли какой-нибудь способ ускорить это?

Комментарии:

1. Я скопировал код как есть. cache1['A'] это была внутренняя вещь (в основном ключ к кэшу), поэтому, возможно, это сбивало с толку. Я исправил это сейчас.

2. Последняя запись в cache2 , не должна ли она быть {'id2': 38472837} вместо {'id': 38472837} ?

3. @CTZhu: вы почти наверняка правы.

4. @DSM, в этом случае, возможно multiindex , это будет подходящий подход, давайте посмотрим, что говорит OP.

Ответ №1:

Я подозреваю, что ваш ndarr , если он выражен как 2d np.array , всегда имеет форму n,m , где n — длина cache1.id1 и m — длина cache2.id2 . И последняя запись в cache2 должна быть {'id2': 38472837} вместо {'id': 38472837} . Если это так, то следующее простое решение может быть всем, что нужно:

 In [30]:

df=pd.DataFrame(np.array(ndarr).ravel(),
             index=pd.MultiIndex.from_product([cache1.id1.values, cache2.id2.values],names=['idx1', 'idx2']),
             columns=['val'])
In [33]:

print df.reset_index()
       idx1      idx2  val
0   ABC1234   3276827  4.3
1   ABC1234  98567498  5.6
2   ABC1234  38472837  6.7
3  NCMN7838   3276827  3.2
4  NCMN7838  98567498  4.5
5  NCMN7838  38472837  2.1

[6 rows x 3 columns]
 

На самом деле, я также думаю, что сохранить его MultiIndex , возможно, будет лучшей идеей.

Ответ №2:

Что-то вроде этого должно работать:

 ndarr = np.asarray(ndarr) # if ndarr is actually an array, skip this
fast_df = pd.DataFrame({"value": ndarr.ravel()})
i1, i2 = [i.ravel() for i in np.indices(ndarr.shape)]
fast_df["id1"] = cache1["id1"].loc[i1].values
fast_df["id2"] = cache2["id2"].loc[i2].values
 

что дает

 >>> fast_df
   value       id1       id2
0    4.3   ABC1234   3276827
1    5.6   ABC1234  98567498
2    6.7   ABC1234       NaN
3    3.2  NCMN7838   3276827
4    4.5  NCMN7838  98567498
5    2.1  NCMN7838       NaN
 

И затем, если вы действительно хотите удалить нулевые значения, вы можете использовать только ненулевые fast_df = fast_df[fast_df['value'] != 0] .