使用字典制作和更新多个 pandas 数据帧(避免重复代码)

making and updating multiple pandas dataframes using dicts (avoiding repetative code)

我有一个 ID 号数据框(n = 140,但可能更多或更少)并且我有 5 个组长。每个组长需要随机分配一定数量的这些 id(为方便起见,让 n=28,但我需要能够控制数量)并且这些行需要拆分成一个新的 df 然后从原始数据帧中删除,以便领导者之间没有交叉。

import pandas as pd
import numpy as np

#making the df
df = pd.DataFrame()
df['ids'] = np.random.randint(1, 140, size=140)
df['group_leader'] = ''


# list of leader names
leaders = ['John', 'Paul', 'George', 'Ringo', 'Apu']

我可以用类似

的东西为每个领导者做这件事
df.loc[df.sample(n=28).index, 'group_leader'] = 'George'
g = df[df['group_leader']=='George'].copy()
df = df[df['group_leader] != 'George']
print(df.shape()[0]) #double checking that df has less ids in it

然而,为每个组长单独执行此操作似乎真的不符合 pythonic(并不是说我是这方面的专家)并且不容易重构为一个函数。

我想我可以用 dictfor loop

frames = dict.fromkeys('group_leaders', pd.DataFrame())

for i in frames.keys(): #allows me to fill the cells with the string key?
    df.loc[df.sample(n=28).index, 'group_leader'] = str(i)
    frames[i].update(df[df['group_leader']== str(i)].copy())#also tried append()
    print(frames[i].head())
    df = df[df['group_leader'] != str(i)]
    print(f'df now has {df.shape[0]} ids left') #just in case there's a remainder of ids

但是,新的数据帧仍然是空的,我收到错误消息:

    Traceback (most recent call last):
  File "C:\Users\path\to\the\file\file.py", line 38, in <module>
    df.loc[df.sample(n=28).index, 'group_leader'] = str(i)
  File "C:\Users\path\to\the\file\pandas\core\generic.py", line 5356, in sample
    locs = rs.choice(axis_length, size=n, replace=replace, p=weights)
  File "mtrand.pyx", line 909, in numpy.random.mtrand.RandomState.choice
ValueError: a must be greater than 0 unless no samples are taken

这让我相信我做错了两件事:

  1. 字典制作不正确或更新不正确。
  2. 使 for 循环 运行 尝试 运行 1 的次数过多。

我已尽力做到尽可能清楚,并提供了我所需要的最低限度有用的版本,如有任何帮助,我们将不胜感激。

注意 - 我知道 5 可以很好地除以 140,但在某些情况下可能不是这种情况,但我很确定如果需要,我可以用 if-else 自己处理。

您可以使用 np.repeatnp.random.shuffle:

leaders = ['John', 'Paul', 'George', 'Ringo', 'Apu']
leaders = np.repeat(leaders, 28)
np.random.shuffle(leaders)
df['group_leader'] = leaders

输出:

>>> df
     ids group_leader
0    138         John
1     36          Apu
2     99         John
3     91       George
4     58        Ringo
..   ...          ...
135   43        Ringo
136   84          Apu
137   94         John
138   56        Ringo
139   58         Paul

[140 rows x 2 columns]

>>> df.value_counts('group_leader')
group_leader
Apu       28
George    28
John      28
Paul      28
Ringo     28
dtype: int64

更新

df = pd.DataFrame({'ids': np.random.randint(1, 113, size=113)})

leaders = ['John', 'Paul', 'George', 'Ringo', 'Apu']
leaders = np.repeat(leaders, np.ceil(len(df) / len(leaders)))
np.random.shuffle(leaders)
df['group_leader'] = leaders[:len(df)]

输出:

>>> df.value_counts('group_leader')
group_leader
Apu       23
John      23
Ringo     23
George    22
Paul      22
dtype: int64