Python 重建数据帧字典的有效方法

Python 重建数据帧字典的有效方法,python,pandas,performance,dictionary,structure,Python,Pandas,Performance,Dictionary,Structure,我有一本充满了多个数据帧的字典。现在我正在寻找一种有效的方法来改变密钥结构,但是当涉及更多的数据帧/更大的数据帧时,我发现的解决方案相当缓慢。这就是为什么我想问是否有人知道一种比我更方便/高效/快捷的方法或途径。首先,我创建了这个示例来说明我最初从哪里开始: import pandas as pd import numpy as np # assign keys to dic teams = ["Arsenal", "Chelsea", "Ma

我有一本充满了多个数据帧的字典。现在我正在寻找一种有效的方法来改变密钥结构,但是当涉及更多的数据帧/更大的数据帧时,我发现的解决方案相当缓慢。这就是为什么我想问是否有人知道一种比我更方便/高效/快捷的方法或途径。首先,我创建了这个示例来说明我最初从哪里开始:

import pandas as pd
import numpy as np

# assign keys to dic
teams = ["Arsenal", "Chelsea", "Manchester United"]
dic_teams = {}

# fill dic with random entries
for t1 in teams:

    dic_teams[t1] = pd.DataFrame({'date': pd.date_range("20180101", periods=30), 
                                  'Goals': pd.Series(np.random.randint(0,5, size = 30)),
                                  'Chances': pd.Series(np.random.randint(0,15, size = 30)),
                                  'Fouls': pd.Series(np.random.randint(0, 20, size = 30)),
                                  'Offside': pd.Series(np.random.randint(0, 10, size = 30))})

    dic_teams[t1] = dic_teams[t1].set_index('date')
    dic_teams[t1].index.name = None
现在我基本上有一个字典,其中每个关键点都是一个团队,这意味着我有一个数据框架,每个团队都有一段时间的游戏性能信息。现在我更愿意修改这个特定的字典,这样我就得到了一个结构,其中键是日期,而不是团队。这意味着每个日期都有一个数据框,其中包含了每个团队在该日期的表现。我使用以下代码成功地做到了这一点,但一旦我添加了更多的团队和性能因素,代码就会非常慢:

# prepare lists for looping
dates = dic_teams["Arsenal"].index.to_list()
perf = dic_teams["Arsenal"].columns.to_list()
dic_dates = {}

# new structure where key = date
for d in dates:
    dic_dates[d] = pd.DataFrame(index = teams, columns = perf)

    for t2 in teams:
        dic_dates[d].loc[t2] = dic_teams[t2].loc[d]
因为我使用的是嵌套循环,所以字典的重构速度很慢。有人知道我如何改进第二段代码吗?我不一定只是在寻找解决方案,也不一定是在寻找如何做得更好的逻辑或想法

提前感谢您,我们非常感谢您提供的任何帮助

您创建熊猫数据帧的方式(奇怪地)非常慢,而且索引也非常直接

复制数据帧的速度惊人地快。因此,可以使用多次复制的空引用数据帧。代码如下:

dates=dic_团队[“阿森纳”]。索引。到_列表()
perf=dic_团队[“阿森纳”]。列。至_列表()
合子=pd.DataFrame(索引=团队,列=性能)
dic_日期={}
#新结构,其中key=date
对于d in日期:
dic_日期[d]=合子拷贝()
对于团队中的t2:
dic_日期[d]。loc[t2]=dic_团队[t2]。loc[d]
这比我机器上的参考速度快2倍左右

克服数据帧直接索引速度慢的问题很棘手。我们可以用numpy来做这件事。实际上,我们可以将数据帧转换为3D numpy数组,使用numpy执行转置,最后再次将切片转换为数据帧。注意,这种方法假设所有值都是整数,并且输入数据帧结构良好

以下是最终实施:

dates=dic_团队[“阿森纳”]。索引。到_列表()
perf=dic_团队[“阿森纳”]。列。至_列表()
dic_日期={}
#从数据帧创建numpy数组
#假设所有数据帧中'dates'和'perf'索引的顺序相同(及其顺序)
full=np.empty(shape=(len(团队)、len(日期)、len(性能)),dtype=int)
对于tId,枚举中的tName(团队):
完整的[tId,:,:]=dic_团队[tName]。to_numpy()
#新结构,其中key=date,从numpy数组创建
对于dId,枚举中的dName(日期):
dic_dates[dName]=pd.DataFrame({pName:full[:,dId,pId]用于pId,枚举(perf)中的pName},index=teams)

此实现比我机器上的参考速度快6.4倍。请注意,大约75%的时间花在
pd.DataFrame
调用上。因此,如果您想要更快的代码,请使用基本的3D numpy数组

亲爱的杰罗姆,非常感谢你的回答。我在我的真实代码上尝试了复制方法,它确实提高了性能!我想尝试numpy方法,但不幸的是,我的数据帧没有整数,而是浮点数。在使用浮点数时,是否也可以转换为(或再次转换为)这样的numpy数组结构?@Sanoj是的,您可以使用
dtype=float
而不是
dtype=int
。这意味着所有的值都将是float类型(即没有字符串)。@Jerome在我的代码中实现了你的方法之后,我完全崩溃了。因为我正在处理这么大的一本字典,它将计算时间从10分钟减少到30秒。我真的需要切换到更多地使用numpy阵列,而不是数据帧。