【问题标题】:Element-wise random choice of a Series of lists (without a loop)一系列列表的元素随机选择(没有循环)
【发布时间】:2020-11-13 21:10:54
【问题描述】:

我想从一系列列表中的每个列表中随机选择一个元素。

import pandas as pd
import numpy as np

l=[['a','b','c'],['d','e','f'],['g','h','i'],['j','k','l'],['m','n','o']]
s = pd.Series(l)

所以s 是:

0    [a, b, c]
1    [d, e, f]
2    [g, h, i]
3    [j, k, l]
4    [m, n, o]
dtype: object

我知道我可以做到以下几点:

s = pd.Series([np.random.choice(i) for i in s])

哪个有效:

0    a
1    e
2    h
3    j
4    m
dtype: object

但我想知道是否有非循环方法可以做到这一点?

例如,(假设每个list 的大小相同)您可以创建一个随机索引数组来尝试从每个list 中选择不同的元素:

i = np.random.randint(3, size=len(l))
#array([2, 2, 0, 1, 0])

但是说s[i] 是行不通的,因为这是索引s 而不是应用到每个list

2    [g, h, i]
2    [g, h, i]
0    [a, b, c]
1    [d, e, f]
0    [a, b, c]
dtype: object

我的动机是拥有可以在大量列表上工作的东西,从而避免循环。但如果我的列表理解似乎是最合理的,或者没有内置的 pandas/numpy 函数,请告诉我。

【问题讨论】:

  • 我认为这可能是最好的方法 s = pd.Series([np.random.choice(i) for i in s])

标签: python pandas list numpy


【解决方案1】:

您可以尝试explode,随机播放爆炸系列,然后进行采样。这甚至不需要列表具有相同的长度。

(s.explode()
   .sample(frac=1, random_state=1)  # random_state added for repeatability, drop if needed
   .groupby(level=0).head(1)
)

输出:

1    d
2    h
0    c
3    k
4    n
dtype: object

【讨论】:

  • 很酷的方法,谢谢分享!我的电脑上的数据似乎也超过了list 理解
【解决方案2】:

我只能这样想,但是性能可能是问题

np.array(s.tolist())[np.arange(len(s)), np.random.randint(3, size=len(s))]
array(['c', 'e', 'i', 'k', 'n'], dtype='<U1')

一些时间

%timeit s.explode().sample(frac=1, random_state=1) 
5.05 ms ± 294 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit pd.Series([np.random.choice(i) for i in s])
23.1 ms ± 184 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit np.array(s.tolist())[np.arange(len(s)), np.random.randint(3, size=len(s))]
1.63 ms ± 50.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

【讨论】:

    猜你喜欢
    • 2021-12-30
    • 1970-01-01
    • 2012-03-12
    • 2013-10-19
    • 2023-01-11
    • 1970-01-01
    • 1970-01-01
    • 2011-05-29
    • 2018-03-06
    相关资源
    最近更新 更多