python使用 "template list"创建新列表

标签 python numpy

假设我有:

x1 = [1, 3, 2, 4]
和:
x2 = [0, 1, 1, 0]
具有相同的形状
现在我想“将 x2 放在 x1 的顶部”并将 x1 的所有数字与 x2 的数字相加
所以最终结果是:
end = [1+4 ,3+2]  # end[0] is the sum of all numbers of x1 where a 0 was in x2
这是使用列表进一步澄清问题的幼稚实现
store_0 = 0
store_1 = 0
x1 = [1, 3, 4, 2]
x2 = [0, 1, 1, 0]
for value_x1 ,value_x2 in zip(x1 ,x2):
    if value_x2 == 0:
        store_0 += value_x1
    elif value_x2 == 1:
        store_1 += value_x1
所以我的问题:
有没有办法在 numpy 中实现这个而不需要
使用循环还是一般更快?

最佳答案

在这个特定的例子中(通常,对于 uniqueduplicatedgroupby 类型的操作), pandas比纯 numpy 快解决方案:
一个 pandas方式,使用 Series (信用:与@mcsoini 的回答非常相似):

def pd_group_sum(x1, x2):
    return pd.Series(x1, index=x2).groupby(x2).sum()
一个纯numpy方式,使用 np.unique和一些花哨的索引:
def np_group_sum(a, groups):
    _, ix, rix = np.unique(groups, return_index=True, return_inverse=True)
    return np.where(np.arange(len(ix))[:, None] == rix, a, 0).sum(axis=1)
注:更好的纯numpy方式的灵感来自@伍德福德的回答:
def selsum(a, g, e):
    return a[g==e].sum()

vselsum = np.vectorize(selsum, signature='(n),(n),()->()')

def np_group_sum2(a, groups):
    return vselsum(a, groups, np.unique(groups))
又一个纯粹的numpy way 的灵感来自@mapf 关于使用 argsort() 的评论.这本身已经需要 45 毫秒,但我们可以尝试基于 np.argpartition(x2, len(x2)-1) 的一些东西。相反,因为在下面的基准测试中它本身只需要 7.5 毫秒:
def np_group_sum3(a, groups):
    ix = np.argpartition(groups, len(groups)-1)
    ends = np.nonzero(np.diff(np.r_[groups[ix], groups.max() + 1]))[0]
    return np.diff(np.r_[0, a[ix].cumsum()[ends]])
(略有修改)示例
x1 = np.array([1, 3, 2, 4, 8])  # I added a group for sake of generality
x2 = np.array([0, 1, 1, 0, 7])

>>> pd_group_sum(x1, x2)
0    5
1    5
7    8

>>> np_group_sum(x1, x2)  # and all the np_group_sum() variants
array([5, 5, 8])
速度
n = 1_000_000
x1 = np.random.randint(0, 20, n)
x2 = np.random.randint(0, 20, n)

%timeit pd_group_sum(x1, x2)
# 13.9 ms ± 65.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit np_group_sum(x1, x2)
# 171 ms ± 129 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

%timeit np_group_sum2(x1, x2)
# 66.7 ms ± 19.4 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

%timeit np_group_sum3(x1, x2)
# 25.6 ms ± 41.3 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
通过 Pandas 速度更快,部分原因是 numpy issue 11136 .

关于python使用 "template list"创建新列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67272291/

相关文章:

numpy - 跳过 genfromtxt 中的行

python - sympy 矩阵真的那么慢吗?

python - Beatbox:拉取SFDC数据时可以添加查询条件吗?

python - 在python中相互添加datetime.time对象

python 和 ehem 安装

python - 如何为我的数据集标记或勾选 Pandas?

python - 如何将数组的一行乘以向量相应行中存储的值?

python - Python 中的频率分析

python - 整个 python 应用程序中的单个数据库连接(遵循单例模式)

python - 发布API授权