Добавить массив numpy в качестве столбца во фрейм данных Pandas

85

У меня есть объект фрейма данных Pandas формы (X, Y), который выглядит так:

[[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]

и многочисленная разреженная матрица (CSC) формы (X, Z), которая выглядит примерно так

[[0, 1, 0],
[0, 0, 1],
[1, 0, 0]]

Как я могу добавить содержимое из матрицы во фрейм данных в новом именованном столбце, чтобы фрейм данных выглядел следующим образом:

[[1, 2, 3, [0, 1, 0]],
[4, 5, 6, [0, 0, 1]],
[7, 8, 9, [1, 0, 0]]]

Обратите внимание, что фрейм данных теперь имеет форму (X, Y + 1), а строки из матрицы являются элементами в фрейме данных.

Михай Дамиан
источник
2
Такое гнездование не рекомендуется. Зачем тебе это нужно?
Филлип Клауд
См. Этот вопрос: stackoverflow.com/q/18641148/564538
Филлип Облако
Я хочу сохранить возможность выбора предыдущего содержимого матрицы по одному имени столбца после слияния.
Михай Дамиан
Почему бы тебе просто не использовать два DataFrameс?
Филлип Клауд

Ответы:

81
import numpy as np
import pandas as pd
import scipy.sparse as sparse

df = pd.DataFrame(np.arange(1,10).reshape(3,3))
arr = sparse.coo_matrix(([1,1,1], ([0,1,2], [1,2,0])), shape=(3,3))
df['newcol'] = arr.toarray().tolist()
print(df)

дает

   0  1  2     newcol
0  1  2  3  [0, 1, 0]
1  4  5  6  [0, 0, 1]
2  7  8  9  [1, 0, 0]
Unutbu
источник
6
Думаю, мы не можем предоставить пуленепробиваемую обувь для пользователей, которые настаивают на таких вещах: /
Филлип Клауд
6
Есть интересные вещи, которые вы можете делать со столбцами списков , поэтому я бы не стал думать, что это обязательно плохая идея. Хотя я согласен, что высока вероятность, что это так.
unutbu 05
1
Это прекрасный пример pandasгибкости. В случае этого вопроса данные уже имеют однородный числовой тип с строками одинаковой формы, тогда как в этом примере они имеют listразную длину. Я согласен с тем, что вы можете делать интересные вещи. Однако, если у вас уже есть матрица, зачем превращать ее в список списков?
Филлип Клауд
1
Есть "интересная вещь" ... сделать его больше не столбцом списков (так что это полезно)!
Энди Хайден
54
Мир становится лучше, когда творческим людям разрешают делать то, что все остальные считают глупостью. :)
unutbu 05
10

Вместо хранения массива в столбце рассмотрите возможность использования структуры данных более высокого измерения ( панели ):

In [11]: p = pd.Panel({'df': df, 'csc': csc})

In [12]: p.df
Out[12]: 
   0  1  2
0  1  2  3
1  4  5  6
2  7  8  9

In [13]: p.csc
Out[13]: 
   0  1  2
0  0  1  0
1  0  0  1
2  1  0  0

Посмотрите на сечения и т. Д. И т. Д. И т. Д.

In [14]: p.xs(0)
Out[14]: 
   csc  df
0    0   1
1    1   2
2    0   3

Подробнее о панелях см. В документации .

Энди Хайден
источник
12
Панель теперь устарела
гухур
Да, в настоящее время обычно рекомендуется MultiIndex. Создано, например, через pd.concat([df, csc], axis=1, keys=["df", "csc"]).
Энди Хайден
A = np.eye(3); df = pd.concat( [A,A], axis=1 )-> TypeError: невозможно объединить объект, отличный от NDFrame в 20.2? (. Вики из «панд-Устаревшие-теперь потребительной этого» было бы неплохо)
денис
@denis tryA = pd.DataFrame(np.eye(3)); df = pd.concat( [A,A], axis=1, keys=["A", "B"] )
Энди Хайден
Спасибо, df.columns MultiIndex(levels=[[u'A', u'B'], [0, 1, 2]](хлопает по лбу)
денис
3

Другой пример:

import numpy as np
import pandas as pd

""" This just creates a list of touples, and each element of the touple is an array"""
a = [ (np.random.randint(1,10,10), np.array([0,1,2,3,4,5,6,7,8,9]))  for i in 
range(0,10) ]

""" Panda DataFrame will allocate each of the arrays , contained as a touple 
element , as column"""
df = pd.DataFrame(data =a,columns=['random_num','sequential_num'])

В общем, секрет состоит в том, чтобы разместить данные в форме a = [(array_11, array_12, ..., array_1n), ..., (array_m1, array_m2, ..., array_mn)] и panda DataFrame упорядочит данные в n столбцах массивов. Конечно, вместо элементов можно использовать массивы массивов, в этом случае форма будет иметь вид: a = [[array_11, array_12, ..., array_1n], ..., [array_m1, array_m2, ..., array_mn ]]

Это результат, если вы напечатаете (df) из приведенного выше кода:

                       random_num                  sequential_num
0  [7, 9, 2, 2, 5, 3, 5, 3, 1, 4]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
1  [8, 7, 9, 8, 1, 2, 2, 6, 6, 3]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
2  [3, 4, 1, 2, 2, 1, 4, 2, 6, 1]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
3  [3, 1, 1, 1, 6, 2, 8, 6, 7, 9]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
4  [4, 2, 8, 5, 4, 1, 2, 2, 3, 3]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
5  [3, 2, 7, 4, 1, 5, 1, 4, 6, 3]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
6  [5, 7, 3, 9, 7, 8, 4, 1, 3, 1]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
7  [7, 4, 7, 6, 2, 6, 3, 2, 5, 6]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
8  [3, 1, 6, 3, 2, 1, 5, 2, 2, 9]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
9  [7, 2, 3, 9, 5, 5, 8, 6, 9, 8]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Другой вариант приведенного выше примера:

b = [ (i,"text",[14, 5,], np.array([0,1,2,3,4,5,6,7,8,9]))  for i in 
range(0,10) ]
df = pd.DataFrame(data=b,columns=['Number','Text','2Elemnt_array','10Element_array'])

Вывод df:

   Number  Text 2Elemnt_array                 10Element_array
0       0  text       [14, 5]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
1       1  text       [14, 5]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
2       2  text       [14, 5]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
3       3  text       [14, 5]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
4       4  text       [14, 5]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
5       5  text       [14, 5]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
6       6  text       [14, 5]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
7       7  text       [14, 5]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
8       8  text       [14, 5]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
9       9  text       [14, 5]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Если вы хотите добавить другие столбцы массивов, то:

df['3Element_array']=[([1,2,3]),([1,2,3]),([1,2,3]),([1,2,3]),([1,2,3]),([1,2,3]),([1,2,3]),([1,2,3]),([1,2,3]),([1,2,3])]

Окончательный вывод df будет:

   Number  Text 2Elemnt_array                 10Element_array 3Element_array
0       0  text       [14, 5]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]      [1, 2, 3]
1       1  text       [14, 5]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]      [1, 2, 3]
2       2  text       [14, 5]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]      [1, 2, 3]
3       3  text       [14, 5]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]      [1, 2, 3]
4       4  text       [14, 5]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]      [1, 2, 3]
5       5  text       [14, 5]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]      [1, 2, 3]
6       6  text       [14, 5]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]      [1, 2, 3]
7       7  text       [14, 5]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]      [1, 2, 3]
8       8  text       [14, 5]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]      [1, 2, 3]
9       9  text       [14, 5]  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]      [1, 2, 3]
Хорхе Вильчис
источник
1

Вы можете добавить и получить массив numpy из фрейма данных, используя это:

import numpy as np
import pandas as pd

df = pd.DataFrame({'b':range(10)}) # target dataframe
a = np.random.normal(size=(10,2)) # numpy array
df['a']=a.tolist() # save array
np.array(df['a'].tolist()) # retrieve array

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

город нормальный
источник
0
df = pd.DataFrame(np.arange(1,10).reshape(3,3))
df['newcol'] = pd.Series(your_2d_numpy_array)
Макс Билески
источник