将列表列转换为 2D numpy 数组

Posted

技术标签:

【中文标题】将列表列转换为 2D numpy 数组【英文标题】:Convert column of lists to 2D numpy array 【发布时间】:2019-06-11 00:36:42 【问题描述】:

我正在对 Pandas 数据框进行一些操作。对于某一列,我需要将每个单元格转换为一个不难的 numpy 数组。最终目标是从整个列中获得一个二维数组。但是,当我执行以下操作时,我得到了一个一维数组,并且无法识别内部数组。

df = pd.DataFrame('col': ['abc', 'def'])
mapping = v: k for k, v in enumerate('abcdef')
df['new'] = df['col'].apply(lambda x: list(x))
df['new'].apply(lambda x: np.array([mapping[i] for i in x])).values

这给出了:

array([array([0, 1, 2]), array([3, 4, 5])], dtype=object)

且形状为 (2,),表示无法识别内部数组。

如果我使用s.reshape(2,-1),我会得到(2,1) 而不是(2,3) 的形状。

感谢任何帮助!


澄清:

以上只是一个玩具示例。我正在做的是使用 IMDB 数据集对机器学习进行预处理。我必须将评论列中的每个值转换为一个词嵌入,它是一个 numpy 数组。现在的挑战是将所有这些数组作为二维数组取出,以便我可以在我的机器学习模型中使用它们。

【问题讨论】:

np.array(df['new'].values.tolist())np.stack(df['new']) @user3483203 tolist() 将意味着它不再是一个数组 @roganjosh 不确定您的意思。如果你省略了tolist,你将得到一个形状为(2,)的对象数组 @user3483203 但仍然是一个 numpy 数组,您可以尝试(如果处于合适的状态)转换其类型。 tolist() 将其放到 python 列表中,您只是要将其转换回数组?你可以把它留在.values吗?还是我错过了什么 @George 你在 Pandas 单元格中寻找嵌套数组吗? 【参考方案1】:

我认为直接从列表值创建一个数组会更好。

 df
   col        new
0  abc  [a, b, c]
1  def  [d, e, f]

arr = np.array(df['new'].tolist())
arr
# array([['a', 'b', 'c'],
#        ['d', 'e', 'f']], dtype='<U1')

arr.shape
# (2, 3)

大免责声明:这仅在子列表都具有相同数量的元素时才有效。如果不是,则意味着它们是参差不齐的数组,并且 numpy 将无法使用有效的内存格式来表示您的数组(因此,dtype='object')。

【讨论】:

concatenate(或其stack 女儿)会将一维对象数组视为列表,并尝试将子数组合并为一个。 @hpaulj 我猜它会慢很多,因为concatenate 正在使用对象数组,对吧? 我们需要做一些计时:) @hpaulj np.stack(df[['new']].values, axis=1) 是否为您提供形状 (2,3) 的二维数组?它似乎不起作用,它们仍然是我的清单。 axis=0 是复制np.array 的版本。【参考方案2】:
In [2]: import pandas as pd
In [3]: df = pd.DataFrame('col': ['abc', 'def'])
   ...: mapping = v: k for k, v in enumerate('abcdef')
   ...: df['new'] = df['col'].apply(lambda x: list(x))

In [7]: df['new']
Out[7]: 
0    [a, b, c]
1    [d, e, f]
Name: new, dtype: object
In [8]: df['new'].values
Out[8]: array([list(['a', 'b', 'c']), list(['d', 'e', 'f'])], dtype=object)

np.stack 的行为很像 np.array,在新的初始轴上连接元素:

In [9]: np.stack(df['new'].values)
Out[9]: 
array([['a', 'b', 'c'],
       ['d', 'e', 'f']], dtype='<U1')

或在您选择的另一个轴上:

In [10]: np.stack(df['new'].values, axis=1)
Out[10]: 
array([['a', 'd'],
       ['b', 'e'],
       ['c', 'f']], dtype='<U1')

np.array 在对象数组变成列表时也可以工作(如@coldspeed 所示):

In [11]: df['new'].values.tolist()
Out[11]: [['a', 'b', 'c'], ['d', 'e', 'f']]
In [12]: np.array(df['new'].values.tolist())
Out[12]: 
array([['a', 'b', 'c'],
       ['d', 'e', 'f']], dtype='<U1')

至于速度,让我们做一个更大的数组:

In [16]: arr = np.frompyfunc(lambda x: np.arange(1000),1,1)(np.arange(1000))
In [17]: arr.shape
Out[17]: (1000,)
In [18]: np.stack(arr).shape
Out[18]: (1000, 1000)
In [20]: np.array(arr.tolist()).shape
Out[20]: (1000, 1000)

In [21]: timeit np.stack(arr).shape
5.24 ms ± 190 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [22]: timeit np.array(arr.tolist()).shape
4.45 ms ± 138 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

基本相同,与np.array 方法相比略有优势。

stack like vstack 根据需要扩展每个元素的维度。用concatenate 跳过它会快一点:

In [27]: timeit np.concatenate(arr).reshape(-1,1000).shape
4.04 ms ± 12.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

这个arr 包含数组。如果它包含列表而不是 array(arr.tolist()) 方法会更好(相对),因为它只有一个列表(列表)转换为数组。 stack 方法必须首先将每个子列表转换为数组。

【讨论】:

以上是关于将列表列转换为 2D numpy 数组的主要内容,如果未能解决你的问题,请参考以下文章

Python将numpy数组的列表转换为2d数组

如何将稀疏的 pandas 数据帧转换为 2d numpy 数组

如何将 2D float numpy 数组转换为 2D int numpy 数组?

将列表列表的字符串转换为 Numpy 数组

将2d数组转换为图像

保持 Numpy 数组 2D