在熊猫中洗牌但有序

Posted

技术标签:

【中文标题】在熊猫中洗牌但有序【英文标题】:Shuffling rows in pandas but orderly 【发布时间】:2020-09-25 09:47:29 【问题描述】:

假设我有一个包含三列的数据框:年龄、性别和国家。

我想根据性别随机打乱这些数据但以有序的方式。有 n 个男性和 m 个女性,其中 n 可以小于、大于或等于 m。改组应该以这样一种方式发生,即我们得到 8 人大小的以下结果:

男,女,男,女,男,女,女,女,....(如果有更多的女性:m > n) 男性,女性,男性,女性,男性,男性,男性,男性(如果有更多男性:n > m) 男,女,男,女,男,女,男,女,男,女(如果男女相等:n = m)

df = pd.DataFrame('Age': [10, 20, 30, 40, 50, 60, 70, 80],
                   'Gender': ["Male", "Male", "Male", "Female", "Female", "Male", "Female", "Female"], 
'Country': ["US", "UK", "China", "Canada", "US", "UK", "China", "Brazil"])

【问题讨论】:

随机但有序的话相互矛盾。 【参考方案1】:

首先添加每个组内的序号:

df['Order'] = df.groupby('Gender').cumcount()

然后排序:

df.sort_values('Order')

它给你:

   Age  Gender Country  Order
0   10    Male      US      0
3   40  Female  Canada      0
1   20    Male      UK      1
4   50  Female      US      1
2   30    Male   China      2
6   70  Female   China      2
5   60    Male      UK      3
7   80  Female  Brazil      3

如果您想随机播放,请从一开始就这样做,例如df = df.sample(frac=1),见:Shuffle DataFrame rows

【讨论】:

我总是忘记.cumcount(),这是一个非常有用的功能。不错。 亲爱的约翰,非常感谢您的策略!有用!使我免于编写带有大量 if/else 条件的 for 循环代码。最重要的是用生奶油,我可以建议大卫修改你的原始代码:sort_values(['Sort_Column', 'Gender'], ascending=[True,False])【参考方案2】:

使用'Sort_Column' 创建两个新数据帧,并使df_male 数据帧为偶数值,df_female 数据帧为奇数值。然后,使用pd.concat 将它们重新组合在一起,并在'Sort_Column' 上使用.sort_values()

df = pd.DataFrame('Age': [10, 20, 30, 40, 50, 60, 70, 80],
                   'Gender': ["Male", "Male", "Male", "Female", "Female", "Male", "Female", "Female"], 
'Country': ["US", "UK", "China", "Canada", "US", "UK", "China", "Brazil"])
df['Sort_Column'] = 0
df_male = df.loc[df['Gender'] == 'Male'].reset_index(drop=True)
df_male['Sort_Column'] = df_male['Sort_Column'] + df_male.index*2
df_female = df1.loc[df1['Gender'] == 'Female'].reset_index(drop=True)
df_female['Sort_Column'] = df_female['Sort_Column'] + df_female.index*2 + 1
df_sorted=pd.concat([df_male, df_female]).sort_values('Sort_Column').drop('Sort_Column', axis=1).reset_index(drop=True)
df_sorted

输出:

    Age Gender  Country
0   10  Male    US
1   40  Female  Canada
2   20  Male    UK
3   50  Female  US
4   30  Male    China
5   70  Female  China
6   60  Male    UK
7   80  Female  Brazil

【讨论】:

@John Zwinck 感谢您的解决方案!非常聪明,我必须说。但是当两个性别的 cumcount 相同时,它就会遇到问题。然后 F->M->F->M 的顺序中断。这是订单中断的示例。一旦他们有共同的指数,性别就不会在男性和女性之间不断切换。你建议我们如何解决这个问题? link 我认为你回答错了:),但你可以这样做:.sort_values(['Sort_Column', 'Gender'], ascending=[True,False]) 亲爱的大卫,我的错!非常感谢您的帮助!这就是我喜欢问题解决者社区的原因!我们共同提出最佳解决方案。 :)

以上是关于在熊猫中洗牌但有序的主要内容,如果未能解决你的问题,请参考以下文章

改组/排列熊猫中的DataFrame

根据熊猫数据框中的列标签对数据进行分组

Redis实战-有序集合

Redis实战-有序集合

5.9 在有序但含有空的数组中查找字符串

Java 有序映射