【问题标题】:Shuffle a DataFrame while keeping internal order在保持内部顺序的同时打乱 DataFrame
【发布时间】:2019-03-08 23:33:18
【问题描述】:

我有一个包含预处理数据的数据框,这样每 4 行就是一个序列(稍后将被重新整形并用于 lstm 训练)。

我想洗牌数据框,但我想保持每个行序列不变。例如: a = [1,2,3,4,10,11,12,13,20,21,22,23] 会变成类似:a = [20,21,22,23,1,2,3,4,10,11,12,13]

df.sample(frac=1) 是不够的,因为它会破坏序列。

解决方案,感谢@Wen-Ben:

seq_length = 4 
length_array = np.arange((df.shape[0]//seq_length)*seq_length)
trunc_data = df.head((df.shape[0]//seq_length)*seq_length)
d = {x : y for x, y in trunc_data.groupby(length_array//seq_length)}
yourdf = pd.concat([d.get(x) for x in np.random.choice(len(d),len(d.keys()),replace=False)])

【问题讨论】:

  • 帧中是否还有其他列每行序列有一个唯一值?例如,对于序列 1、2、3、4,该列可以具有值 1,对于 10、11、12、13,该列可以具有值 2。如果没有,添加这样的列可以吗?
  • @suicidalteddy 1,2,3,4 代表某列的 4 行,而不是一行。我可以添加另一列 - 但它有什么帮助?请记住,许多值会重复

标签: python pandas shuffle


【解决方案1】:

这是你需要的吗,np.random.choice

d={x : y for x, y in df.groupby(np.arange(len(df))//4)}

yourdf=pd.concat([d.get(x) for x in np.random.choice(len(d),2,replace=False)])
yourdf
Out[986]: 
   col1 col2
4     5    e
5     6    f
6     7    g
7     8    h
0     1    a
1     2    b
2     3    c
3     4    d

【讨论】:

  • 这假定索引是数字和连续的。看看我没有做出这样的假设的答案。 (虽然这是对使用 np.roll 的原始答案的改进)
  • @PMaschhoff 你的答案是好的,但仅适用于 df 的 len 为 n*4 时,假设 df 的长度为 6 ,` np.arange(len(df)-2)。 reshape(-1, 4)` , reshape 会失败
  • @Wen-Ben 就是这样!我稍微调整了您的代码-在问题中添加并编辑。谢谢!
【解决方案2】:

您可以以 4 个为一组重新洗牌,方法是...将索引分成四个一组,然后重新洗牌。

例子:

df = pd.DataFrame(np.random.randint(10, size=(12, 2)))
    a  b
0   5  4
1   7  7
2   7  8
3   8  4
4   9  4
5   9  0
6   1  5
7   4  1
8   0  1
9   5  6
10  1  3
11  9  2
new_index = np.array(df.index).reshape(-1, 4)
np.random.shuffle(new_index)  # shuffles array in-place
df = df.loc[new_index.reshape(-1)]
    a  b
8   0  1
9   5  6
10  1  3
11  9  2
4   9  4
5   9  0
6   1  5
7   4  1
0   5  4
1   7  7
2   7  8
3   8  4

【讨论】:

    【解决方案3】:

    正如您所说,您有 4 个序列的数据,那么数据帧的长度应该是 4 的倍数。如果您的数据是 3 个序列,请在代码中将 4 更改为 3。

    >>> import pandas as pd
    >>> import numpy as np
    

    创建表:

    >>> df = pd.DataFrame({'col1':[1,2,3,4,5,6,7,8],'col2':['a','b','c','d','e','f','g','h']})
    >>> df
       col1 col2
    0     1    a
    1     2    b
    2     3    c
    3     4    d
    4     5    e
    5     6    f
    6     7    g
    7     8    h
    >>> df.shape[0]
    8
    

    创建洗牌列表:

    >>> np_range = np.arange(0,df.shape[0])
    >>> np_range
    array([0, 1, 2, 3, 4, 5, 6, 7])
    

    重塑和洗牌:

    >>> np_range1 = np.reshape(np_range,(df.shape[0]/4,4))
    >>> np_range1
    array([[0, 1, 2, 3],
           [4, 5, 6, 7]])
    >>> np.random.shuffle(np_range1)
    >>> np_range1
    array([[4, 5, 6, 7],
           [0, 1, 2, 3]])
    >>> np_range2 = np.reshape(np_range1,(df.shape[0],))
    >>> np_range2
    array([4, 5, 6, 7, 0, 1, 2, 3])
    

    选择数据:

    >>> new_df = df.loc[np_range2]
    >>> new_df
       col1 col2
    4     5    e
    5     6    f
    6     7    g
    7     8    h
    0     1    a
    1     2    b
    2     3    c
    3     4    d
    
    

    我希望这会有所帮助!谢谢!

    【讨论】:

    • @Wen-Ben 滚动旋转数组,即将最后 n 个索引置于开头。它显然没有执行任何洗牌。谢谢!
    • 当df的长度不是n*4时,比如它有6行,reshape会失败吗?
    • @Wen-Ben 是的,它会失败,但这取决于他的数据,当他试图打乱他已经在 4 序列中的数据时。那么整个数据应该是4肯定。如果他的数据序列是 3 的倍数,那么他必须将 4 替换为 3。我的推理是正确的还是我遗漏了什么?
    • 我不确定,这就是我不使用 reshape 的原因。
    • @sambasivarao 谢谢,但最好不要对数据做出假设 - 在我的情况下,有时数据不能完全被 4 整除。请参阅 Wen-Ben 的解决方案和我的编辑。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2018-09-10
    • 2022-01-05
    • 2018-03-31
    • 2016-02-11
    • 2012-06-22
    • 1970-01-01
    • 1970-01-01
    • 2017-09-21
    相关资源
    最近更新 更多