【问题标题】:Obtaining numpy array of shortened lists?获取缩短列表的numpy数组?
【发布时间】:2019-10-18 12:17:09
【问题描述】:

考虑这段代码:

#!/usr/bin/env python3

import numpy as np

aa = [
  [3, 8, [37, 7, 5, 0, 5, 0, 8, 0]],
  [3, 8, [36, 7, 5, 0, 4, 0, 8, 0]],
  [3, 8, [37, 7, 5, 0, 4, 0, 8, 0]],
  [3, 8, [37, 7, 5, 0, 5, 0, 9, 0]],
  [3, 8, [36, 7, 6, 0, 6, 0, 12, 0]],
  [3, 8, [36, 7, 5, 0, 5, 0, 9, 0]],
  [3, 8, [36, 7, 5, 0, 5, 0, 8, 0]],
  [3, 8, [37, 7, 6, 0, 6, 0, 10, 0]],
  [3, 8, [37, 7, 6, 0, 6, 0, 10, 0]],
  [3, 8, [37, 7, 6, 0, 6, 0, 12, 0]]
]

nch = np.asarray(aa, dtype=object)

print("nch shape {}".format(nch.shape))
print(nch)
nchB = nch[:,2]
print("nchB shape {}".format(nchB.shape))
print(nchB)

print("Test 1")
print( np.frompyfunc(list, 0, 1)(np.empty((3,2), dtype=object)) )
print("Test 2")
print( np.frompyfunc(list, 0, 1)(nchB) )
print("Test 3")
print( np.frompyfunc(list, 1, 1)( nchB ) )

它输出:

nch shape (10, 3)
[[3 8 list([37, 7, 5, 0, 5, 0, 8, 0])]
 [3 8 list([36, 7, 5, 0, 4, 0, 8, 0])]
 [3 8 list([37, 7, 5, 0, 4, 0, 8, 0])]
 [3 8 list([37, 7, 5, 0, 5, 0, 9, 0])]
 [3 8 list([36, 7, 6, 0, 6, 0, 12, 0])]
 [3 8 list([36, 7, 5, 0, 5, 0, 9, 0])]
 [3 8 list([36, 7, 5, 0, 5, 0, 8, 0])]
 [3 8 list([37, 7, 6, 0, 6, 0, 10, 0])]
 [3 8 list([37, 7, 6, 0, 6, 0, 10, 0])]
 [3 8 list([37, 7, 6, 0, 6, 0, 12, 0])]]
nchB shape (10,)
[list([37, 7, 5, 0, 5, 0, 8, 0]) list([36, 7, 5, 0, 4, 0, 8, 0])
 list([37, 7, 5, 0, 4, 0, 8, 0]) list([37, 7, 5, 0, 5, 0, 9, 0])
 list([36, 7, 6, 0, 6, 0, 12, 0]) list([36, 7, 5, 0, 5, 0, 9, 0])
 list([36, 7, 5, 0, 5, 0, 8, 0]) list([37, 7, 6, 0, 6, 0, 10, 0])
 list([37, 7, 6, 0, 6, 0, 10, 0]) list([37, 7, 6, 0, 6, 0, 12, 0])]
Test 1
[[list([]) list([])]
 [list([]) list([])]
 [list([]) list([])]]
Test 2
[list([]) list([]) list([]) list([]) list([]) list([]) list([]) list([])
 list([]) list([])]
Test 3
[list([]) list([]) list([]) list([]) list([]) list([]) list([]) list([])
 list([]) list([])]

基本上,我使用 nchB 之类的东西来提供 matplotlib 箱线图,效果很好。

nchB这里被认为是一个长度为10的一维数组,其元素为列表;这里发生了这样的情况,每个列表都有 8 个元素。

现在,我想创建一个数组,它也是一个长度为 10 的单维数组,其元素是列表;除了我希望每个列表只有一个或两个元素。所以我想获得,说:

[list([37, 7]) list([36, 7])
 list([37, 7]) list([37, 7])
 list([36, 7]) list([36, 7])
 list([36, 7]) list([37, 7])
 list([37, 7]) list([37, 7])]

或:

[list([37]) list([36])
 list([37]) list([37])
 list([36]) list([36])
 list([36]) list([37])
 list([37]) list([37])]

... 以某种方式来自nchB,最好使用单线 - 然后我可以使用这个“简化”的列表数组来提供 maxplotlib 的箱线图数据以进行初始化(这样我就可以开始设置绘图了,而不是必须等待很多时间才能呈现我的实际数据)。

我该怎么做?显然,我在上面的“测试 2”和“测试 3”中使用 np.frompyfunc 进行的琐碎尝试,我从以下位置找到的:

...不太好用,因为我得到的只是空列表。

【问题讨论】:

  • 看起来我的建议(在您的链接中)使用np.frompyfunc(list,0,1) 具有误导性。 frompyfunc 非常适合创建对象 dtype 数组。但是这种形式最终会为每个元素调用list(),而不管输入数组是什么,因为0。在大多数情况下,func 需要更精细,接受一个或多个输入 - lambdadef

标签: python arrays list numpy


【解决方案1】:

好的,我想我知道了 - 现在是这段代码:

#!/usr/bin/env python3

import numpy as np

aa = [
  [3, 8, [37, 7, 5, 0, 5, 0, 8, 0]],
  [3, 8, [36, 7, 5, 0, 4, 0, 8, 0]],
  [3, 8, [37, 7, 5, 0, 4, 0, 8, 0]],
  [3, 8, [37, 7, 5, 0, 5, 0, 9, 0]],
  [3, 8, [36, 7, 6, 0, 6, 0, 12, 0]],
  [3, 8, [36, 7, 5, 0, 5, 0, 9, 0]],
  [3, 8, [36, 7, 5, 0, 5, 0, 8, 0]],
  [3, 8, [37, 7, 6, 0, 6, 0, 10, 0]],
  [3, 8, [37, 7, 6, 0, 6, 0, 10, 0]],
  [3, 8, [37, 7, 6, 0, 6, 0, 12, 0]]
]

nch = np.asarray(aa, dtype=object)

print("nch shape {}".format(nch.shape))
print(nch)
nchB = nch[:,2]
print("nchB shape {}".format(nchB.shape))
print(nchB)
#print([i[0] for i in nchB])
#print([ [i[0], i[1]] for i in nchB])
#print(np.asarray([ [i[0], i[1]] for i in nchB], dtype=object))
#print(   np.frompyfunc(list, 1, 1)( np.asarray([ [i[0], i[1]] for i in nchB], dtype=object) )   ) # TypeError: 'int' object is not iterable
#~ print(   np.frompyfunc(list, 1, 1)( [ [i[0], i[1]] for i in nchB] )   )
print(   np.frompyfunc(list, 1, 1)( i for i in nchB )   )

print("Test 1")
print( np.frompyfunc(list, 0, 1)(np.empty((3,2), dtype=object)) )

# print("Test 2")
# print( np.frompyfunc(list, 0, 1)(nchB) )
# print("nchB", nchB) # deleted!? nchB [list([]) list([]) list([]) list([]) list([]) list([]) list([]) list([]) list([]) list([])]

print("Test 3")
print( np.frompyfunc(list, 1, 1)( nchB ) )
#print("nchB", nchB) # OK, but does not create empty lists

print("Test 4")
nchBB = np.copy(nchB) # copy, as nchB will get deleted/changed otherwise
blist = np.frompyfunc(list, 0, 1)( nchBB ) # forces empty list, both blist and nchBB
gen = (item.extend( (nchB[ind][0], nchB[ind][1]) ) for ind, item in enumerate(blist))
for _ in gen: pass # https://stackoverflow.com/q/11539194
print("blist", blist) # blist [list([37, 7]) list([36, 7]) ...
print("nchBB", nchBB) # nchBB [list([37, 7]) list([36, 7]) ...

print("shapes:", blist.shape, nchB.shape)

...将产生:

...
Test 1
[[list([]) list([])]
 [list([]) list([])]
 [list([]) list([])]]
Test 3
[list([37, 7, 5, 0, 5, 0, 8, 0]) list([36, 7, 5, 0, 4, 0, 8, 0])
 list([37, 7, 5, 0, 4, 0, 8, 0]) list([37, 7, 5, 0, 5, 0, 9, 0])
 list([36, 7, 6, 0, 6, 0, 12, 0]) list([36, 7, 5, 0, 5, 0, 9, 0])
 list([36, 7, 5, 0, 5, 0, 8, 0]) list([37, 7, 6, 0, 6, 0, 10, 0])
 list([37, 7, 6, 0, 6, 0, 10, 0]) list([37, 7, 6, 0, 6, 0, 12, 0])]
Test 4
blist [list([37, 7]) list([36, 7]) list([37, 7]) list([37, 7]) list([36, 7])
 list([36, 7]) list([36, 7]) list([37, 7]) list([37, 7]) list([37, 7])]
nchBB [list([37, 7]) list([36, 7]) list([37, 7]) list([37, 7]) list([36, 7])
 list([36, 7]) list([36, 7]) list([37, 7]) list([37, 7]) list([37, 7])]
shapes: (10,) (10,)

所以,诀窍是:

  • 复制源列表的 np.array - 因为使用 np.array 作为 np.frompyfunc 的源将就地更改它!
  • 使 np.frompyfunc 返回空列表,用于源 np.array 中的完整列表
  • 创建一个循环遍历np.frompyfunc 空列表的生成器表达式,并使用源 np.array 的前两个元素扩展这些空列表(现在可以完全访问,因为它已被复制,因此保持不变由np.frompyfunc)

我有点希望这会更容易和/或可以使用单线,但是你去...至少,被截断的nchBB和原来的nchB,现在仍然具有相同的形状,从numpy的角度来看。

【讨论】:

    【解决方案2】:

    你快到了:

    slice_two = np.frompyfunc(lambda x: x[:2], 1, 1)
    slice_two(nchB)
    
    # [list([37, 7]) list([36, 7]) 
    #  list([37, 7]) list([37, 7]) 
    #  list([36, 7]) list([36, 7]) 
    #  list([36, 7]) list([37, 7]) 
    #  list([37, 7]) list([37, 7])]
    
    slice_one = np.frompyfunc(lambda x: x[:1], 1, 1)
    slice_one(nchB)
    
    # [list([37]) list([36]) 
    #  list([37]) list([37]) 
    #  list([36]) list([36])
    #  list([36]) list([37]) 
    #  list([37]) list([37])]
    

    而且这也不影响原始数据:

    print(nchB)
    # [list([37, 7, 5, 0, 5, 0, 8, 0])  list([36, 7, 5, 0, 4, 0, 8, 0])
    #  list([37, 7, 5, 0, 4, 0, 8, 0])  list([37, 7, 5, 0, 5, 0, 9, 0])
    #  list([36, 7, 6, 0, 6, 0, 12, 0]) list([36, 7, 5, 0, 5, 0, 9, 0])
    #  list([36, 7, 5, 0, 5, 0, 8, 0])  list([37, 7, 6, 0, 6, 0, 10, 0])
    #  list([37, 7, 6, 0, 6, 0, 10, 0]) list([37, 7, 6, 0, 6, 0, 12, 0])]
    

    【讨论】:

      猜你喜欢
      • 2020-10-31
      • 2018-05-15
      • 1970-01-01
      • 1970-01-01
      • 2017-05-03
      • 2016-08-26
      • 2022-12-10
      • 1970-01-01
      • 2022-01-25
      相关资源
      最近更新 更多