我有以下numpy数组:
array([['apple','banana','orange'],
['car','bike','train','ship','plane','scooter'],
['red','purple']], dtype=object)
数组中的各行长度不等,我想得到每行的最后一个元素。我可以通过运行for循环来获得这个,但我想可能有更直接的方法。我最接近(错误的解决方案)是arr [:] [ - 1]它给了我最后一行的元素和arr [np.arange(len(arr)), - 1]它会抛出'IndexError'错误。
我想要的输出是:
array([['orange','scooter','purple']], dtype=object)
我将不胜感激任何指导。谢谢。
答案 0 :(得分:1)
使用熊猫:
In [87]: a
Out[87]: array([['apple', 'banana', 'orange'], ['car', 'bike', 'train', 'ship', 'plane', 'scooter'], ['red', 'purple']], dtype=object)
In [88]: df = pd.DataFrame(a)
In [93]: df
Out[93]:
0
0 [apple, banana, orange]
1 [car, bike, train, ship, plane, scooter]
2 [red, purple]
In [94]: df[0].str[-1]
Out[94]:
0 orange
1 scooter
2 purple
Name: 0, dtype: object
或作为NumPy数组:
In [95]: df[0].str[-1].values
Out[95]: array(['orange', 'scooter', 'purple'], dtype=object)
答案 1 :(得分:1)
如果最快,请使用列表清单:
import numpy as np
import random
items = ['apple','banana','orange', 'car','bike','train','ship','plane','scooter', 'red','purple']
a = [random.sample(items, random.randint(2, 10)) for _ in range(1000)]
b = np.array(a)
%timeit [x[-1] for x in a] # 62.1 µs
%timeit [x[-1] for x in b] # 75.9 µs
f = np.frompyfunc(lambda x:x[-1], 1, 1)
%timeit f(b) # 165 µs
import cytoolz
%timeit list(cytoolz.pluck(-1, a)) # 42.7 µs
%timeit list(cytoolz.pluck(-1, b)) # 75.8 µs
import pandas as pd
s = pd.Series(a)
%timeit s.str[-1] # 965 µs
即使您有DataFrame或Series对象,也可以先将其转换为列表:
%timeit s.tolist() #45.6 µs
答案 2 :(得分:0)
使用循环理解:#!/bin/bash
# ^^^^- NOT /bin/sh
content=$(<"$ssh_key") # more efficient alternative to $(cat ...)
# generate shell-quoted versions of your variables
# these are safe to substitute into a script
# ...even if the original content contains evil things like $(rm -rf /*)
printf -v content_q '%q' "$content"
printf -v new_user_q '%q' "$new_user"
# use those shell-quoted versions remotely
sshpass -f"$password_file" ssh "$host" bash -s <<EOF
adduser ${new_user_q}
printf '%s\n' ${content_q} >>/home/${new_user_q}/.ssh/authorized_keys
EOF
可能只是一种有效而快速的方法,特别是如果列表足够长的话。但是既然你要求一个非循环的解决方案,这里有一种方法可以使用np.concatenate
来获得一个扁平版本,然后使用适当的索引将其编入索引,以便选择每个列表的最终元素 -
np.array([i[-1] for i in arr],dtype=object)
有np.concatenate(arr)[np.cumsum(map(len,arr))-1]
运算符的使用,它看起来不像向量化操作,但由于我们只使用它来获取列表的长度,因此该部分在运行时不应该很重。所以,我想这是一种几乎矢量化的方法。
示例运行 -
map
请注意,如果我们想要一个对象dtype数组,我们需要在编制索引之前转换为这样的dtype:In [166]: arr
Out[166]:
array([['apple', 'banana', 'orange'],
['car', 'bike', 'train', 'ship', 'plane', 'scooter'],
['red', 'purple']], dtype=object)
In [167]: np.concatenate(arr)[np.cumsum(map(len,arr))-1]
Out[167]:
array(['orange', 'scooter', 'purple'],
dtype='|S7')
。