python - 我如何快速洗牌 Pandas 系列

标签 python pandas numpy

假设我有 pd.Series

import pandas as pd
import numpy as np

s = pd.Series(np.arange(10), list('abcdefghij'))

我想通过将上半部分和下半部分交织在一起,像一副纸牌一样“洗牌”这个系列。

我希望这样的结果

a    0
f    5
b    1
g    6
c    2
h    7
d    3
i    8
e    4
j    9
dtype: int32

结论
最终功能

def perfect_shuffle(s):
    n = s.values.shape[0]  # get length of s
    l = (n + 1) // 2 * 2   # get next even number after n
    # use even number to reshape and only use n of them after ravel
    a = np.arange(l).reshape(2, -1).T.ravel()[:n]
    # construct new series slicing both values and index
    return pd.Series(s.values[a], s.index.values[a])

示范

s = pd.Series(np.arange(11), list('abcdefghijk'))
print(perfect_shuffle(s))

a     0
g     6
b     1
h     7
c     2
i     8
d     3
j     9
e     4
k    10
f     5
dtype: int64

order='F'T
我曾建议使用 T.ravel() 而不是 ravel(order='F')
经过调查,这无关紧要,但 ravel(order='F') 对于较大的数组更好。

d = pd.DataFrame(dict(T=[], R=[]))

for n in np.power(10, np.arange(1, 8)):
    a = np.arange(n).reshape(2, -1)
    stamp = pd.datetime.now()
    for _ in range(100):
        a.ravel(order='F')
    d.loc[n, 'R'] = (pd.datetime.now() - stamp).total_seconds()
    stamp = pd.datetime.now()
    for _ in range(100):
        a.T.ravel()
    d.loc[n, 'T'] = (pd.datetime.now() - stamp).total_seconds()

d

enter image description here

d.plot()

enter image description here


感谢 unutbuWarren Weckesser

最佳答案

在 Series 的长度为偶数的特殊情况下,您可以执行 perfectly shuffle通过将其值 reshape 为两行,然后使用 ravel(order='F')以 Fortran 顺序读取项目:

In [12]: pd.Series(s.values.reshape(2,-1).ravel(order='F'), s.index)
Out[12]: 
a    0
b    5
c    1
d    6
e    2
f    7
g    3
h    8
i    4
j    9
dtype: int64

Fortran 顺序使最左边的轴增量最快。所以在二维数组中 在前进到之前,通过向下一列的行读取值 下一栏。与 通常的 C 顺序。


在 Series 的长度可能为奇数的一般情况下, 也许最快的方法是使用移位切片重新分配值:

import numpy as np
import pandas as pd

def perfect_shuffle(ser):
    arr = ser.values
    result = np.empty_like(arr)
    N = (len(arr)+1)//2
    result[::2] = arr[:N]
    result[1::2] = arr[N:]
    result = pd.Series(result, index=ser.index)
    return result

s = pd.Series(np.arange(11), list('abcdefghijk'))
print(perfect_shuffle(s))

产量

a     0
b     6
c     1
d     7
e     2
f     8
g     3
h     9
i     4
j    10
k     5
dtype: int64

关于python - 我如何快速洗牌 Pandas 系列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40187126/

相关文章:

python - 如何附加到 numpy 数组而不将结果重新分配给新变量?

python - 如何在三元素数组中找到唯一元素?

python - 从python中的span类获取数据

python - 根据列中找到的阈值向上移动 DataFrame 列

python - 两个数据框中按索引的公共(public)元素数

python - 如何计算滚动窗口中数据框的列中相同实例的数量

python - syslog 中的多行日志记录

python - 如何在 Python 中创建 CFuncType

python - 如何移动数据框的日期?

python - 将 numpy 数组类型和值从 Float64 转换为 Float32