【问题标题】:making and updating multiple pandas dataframes using dicts (avoiding repetative code)使用 dicts 制作和更新多个 pandas 数据帧(避免重复代码)
【发布时间】:2022-01-23 12:52:56
【问题描述】:

我有一个 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

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

我认为我可以使用 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 自己处理。

【问题讨论】:

    标签: python pandas dataframe dictionary refactoring


    【解决方案1】:

    您可以使用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
    

    【讨论】:

    • 让我知道这是否是您真正期望的,因为我不确定是否真的能得到您想要的。
    • 这很酷,谢谢,但我需要更多的控制,以防我需要为组长分配不同数量的 id。我显然需要更好地表达这个问题,谢谢你的评论
    • 你的意思是像n = len(df) / len(leaders)这样的吗?
    • 我更新了我的答案。你能检查一下吗?也许它应该回答你的下一部分:)
    • 非常感谢,我需要做一些重新工作以使其适合整个项目,但这是一个很好的答案,谢谢。
    猜你喜欢
    • 2016-07-05
    • 2016-03-31
    • 2019-10-05
    • 2015-05-03
    • 2014-03-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多