将列表列转换为二维numpy数组

5

我正在对Pandas数据帧进行一些操作。对于某个列,我需要将每个单元格转换为numpy数组,这并不难。最终目标是从整个列中获得一个2D数组作为结果。然而,当我执行以下操作时,我得到了一个1D数组,并且内部数组没有被识别。

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数组。现在的挑战是将所有这些数组作为2D数组输出,以便我可以在我的机器学习模型中使用它们。

1
np.array(df['new'].values.tolist()) or np.stack(df['new']) - user3483203
@user3483203 tolist() 的意思是它不再是一个数组。 - roganjosh
@roganjosh 不确定您的意思。如果您去掉tolist,那么您将会得到一个类型为对象,形状为(2,)的数组。 - user3483203
@user3483203 但仍然是一个numpy数组,您可以尝试(如果处于适当状态)转换其类型。 tolist() 将其转换为Python列表,然后您将其转换回数组?您可以只保留 .values 吗?或者我有什么遗漏的吗? - roganjosh
是的,我预期一个形状为(2,3)的数组。 - George Liu
显示剩余4条评论
2个回答

7
我认为直接从列表值创建数组会更好。
 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”子类之一)将把1d对象数组视为列表,并尝试将子数组连接成一个数组。 - hpaulj
@hpaulj 我猜它会慢很多,因为 concatenate 是在使用对象数组,对吧? - cs95
我们需要进行一些计时 :) - hpaulj
@hpaulj np.stack(df[['new']].values, axis=1) 给你一个形状为(2,3)的二维数组吗?它似乎不起作用,对我来说它们仍然是列表。 - cs95
axis=0 是复制 np.array 的版本。 - hpaulj

0
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方法。

stackvstack一样根据需要扩展每个元素的维度。使用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 方法则必须先将每个子列表都转换为数组。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接