我有一个列表列表(变量len),需要转换为numpy数组。例子:
import numpy as np
sample_list = [["hello", "world"], ["foo"], ["alpha", "beta", "gamma"], []]
sample_arr = np.asarray(sample_list)
>>> sample_arr
array([list(['hello', 'world']), list(['foo']),
list(['alpha', 'beta', 'gamma']), list([])], dtype=object)
>>> sample_arr.shape
(4,)
在上面的例子中,我得到了一个想要的一维数组。代码的下游模块期望相同。然而,当列表具有相同长度时,它输出一个二维数组,导致我的代码的下游模块出错:
sample_list = [["hello"], ["world"], ["foo"], ["bar"]]
sample_arr = np.asarray(sample_list)
>>>
>>> sample_arr
array([['hello'],
['world'],
['foo'],
['bar']], dtype='<U5')
>>> sample_arr.shape
(4, 1)
相反,我希望输出类似于第一个示例:
>>> sample_arr
array([list(['hello']), list(['world']),
list(['foo']), list(['bar'])], dtype=object)
我有什么办法可以做到吗?
在第一种情况下,np.array
给我们一个警告(在新的numpy版本中)。这应该告诉我们一些东西-使用np.array
来制作不规则数组并不理想。np.array
意味着创建常规多维数组,与数字(或字符串)dtypes。创建像这样的对象类型数组是一个备用选项。
In [96]: sample_list = [["hello", "world"], ["foo"], ["alpha", "beta", "gamma"], []]
In [97]: arr = np.array(sample_list)
<ipython-input-97-ec7d58f98892>:1: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray.
arr = np.array(sample_list)
In [98]: arr
Out[98]:
array([list(['hello', 'world']), list(['foo']),
list(['alpha', 'beta', 'gamma']), list([])], dtype=object)
在许多方面,这样的数组是一个降级的列表,而不是一个真正的数组。
在第二种情况下,它可以按预期工作(由开发人员,如果不是你!):
In [99]: sample_list = [["hello"], ["world"], ["foo"], ["bar"]]
In [100]: arr = np.array(sample_list)
In [101]: arr
Out[101]:
array([['hello'],
['world'],
['foo'],
['bar']], dtype='<U5')
为了解决这个问题,我建议创建一个大小合适的对象dtype数组,并从列表中填充它:
In [102]: arr = np.empty(len(sample_list), object)
In [103]: arr
Out[103]: array([None, None, None, None], dtype=object)
In [104]: arr[:] = sample_list
In [105]: arr
Out[105]:
array([list(['hello']), list(['world']), list(['foo']), list(['bar'])],
dtype=object)
是的,这是可能的!您可以定义一个函数,将列表的列表转换为包含所有项的单个列表,如下所示:
import numpy as np
def flatten_list(nested_list):
single_list = []
for item in nested_list:
single_list.extend(item)
return single_list
sample_arr = np.asarray(flatten_list([["hello", "world"], ["foo"], ["alpha", "beta", "gamma"], []]))
print(sample_arr)
一种快速而肮脏的python方法,你可以使用列表推导式:
sample_arr = np.asarray([[j] for sub in sample_list for j in sub])
如果你感兴趣的话,这里有更多关于列表解析的信息:https://www.w3schools.com/python/python_lists_comprehension.asp