Python,在df的字典中迭代和修改数据帧

Python,在df的字典中迭代和修改数据帧,python,pandas,optimization,vectorization,Python,Pandas,Optimization,Vectorization,多年前,我来自C语言背景,对Python非常陌生,我正在努力优化我的代码。实际上,我们刚刚了解到for循环非常慢 在下面的代码中,向Dict中的每个数据帧添加计算列的循环似乎是一个巨大的瓶颈 我读过一些解决这个问题的方法,比如;但我认为我对Python的了解还不够,无法真正理解和使用它们 事实上,除了我用np.where做的一个测试外,我对这两种方法的尝试都失败了,可能是错误的实现。这表明我的for循环/计算有多糟糕 在我的工作示例中,我将省略这些尝试,但如果需要,可以稍后添加: import

多年前,我来自C语言背景,对Python非常陌生,我正在努力优化我的代码。实际上,我们刚刚了解到for循环非常慢

在下面的代码中,向Dict中的每个数据帧添加计算列的循环似乎是一个巨大的瓶颈

我读过一些解决这个问题的方法,比如;但我认为我对Python的了解还不够,无法真正理解和使用它们

事实上,除了我用np.where做的一个测试外,我对这两种方法的尝试都失败了,可能是错误的实现。这表明我的for循环/计算有多糟糕

在我的工作示例中,我将省略这些尝试,但如果需要,可以稍后添加:

import pandas as pd
import numpy as np
import datetime as date
import itertools

def points(row):
val = 0
if row['Ob2'] > 0.5:
    foo = row['Ob3'] - row['Ob1']
    if foo < 0.1:
        val = 1 - foo
else:
    val = 0
return val

print("Start: "+ str(date.datetime.now()))
print()

player_list = ['player' + str(x) for x in range(1,71)]

data = pd.DataFrame({'Names': player_list*1000,\
                   'Ob1' : np.random.rand(70000),\
                   'Ob2' : np.random.rand(70000) ,\
                   'Ob3' : np.random.rand(70000)})

#create list of unique pairs
comboNames = list(itertools.combinations(data.Names.unique(), 2))

#create a data frame dictionary to store your data frames
DataFrameDict = {elem : pd.DataFrame for elem in comboNames}

for key in DataFrameDict.keys():
    DataFrameDict[key] = data[:][data.Names.isin(key)]
    DataFrameDict[key] = DataFrameDict[key].sort_values(['Ob1'])

print("DF fill: "+ str(date.datetime.now()))
print()

#Add test calculated column
for tbl in DataFrameDict:
    DataFrameDict[tbl]['Test'] = DataFrameDict[tbl].apply(points, axis=1) #Slow loop
    #example vectorised, hugh dif is run time
    #DataFrameDict[tbl]['Test'] = np.where((DataFrameDict[tbl]['Ob2']>0.5),1,0)

print("Calc'd: "+ str(date.datetime.now()))
print()

headers = ['Player1','Player2','Score','Count']
summary = pd.DataFrame(([tbl[0], tbl[1], DataFrameDict[tbl]['Test'].sum(),
                      DataFrameDict[tbl]['Test'].astype(bool).sum(axis=0)] for tbl in DataFrameDict),
                      columns=headers).sort_values(['Score'], ascending=[False])

print("Fin: "+ str(date.datetime.now()))
print()
我的朋友,因为杂乱无章,不想在这里发帖

import pandas as pd
import numpy as np
import datetime as date
import itertools

player_list = ['player' + str(x) for x in range(1,71)]

data = pd.DataFrame({'Names': player_list*1000,\
                   'Ob1' : np.random.rand(70000),\
                   'Ob2' : np.random.rand(70000) ,\
                   'Ob3' : np.random.rand(70000)})

data['Test'] = np.where(data['Ob2'] > 0.5, np.where(data['Ob3'] - data['Ob1'] < 0.1, 1 - (data['Ob3'] - data['Ob1']), 0), 0)


comboNames = list(itertools.combinations(data.Names.unique(), 2))
DataFrameDict = {elem : pd.DataFrame for elem in comboNames}

for key in DataFrameDict.keys():
    DataFrameDict[key] = data[:][data.Names.isin(key)]
    DataFrameDict[key] = DataFrameDict[key].sort_values(['Ob1'])

headers = ['Player1','Player2','Score','Count']
summary = pd.DataFrame(([tbl[0], tbl[1], DataFrameDict[tbl]['Test'].sum(),
                      DataFrameDict[tbl]['Test'].astype(bool).sum(axis=0)] for tbl in DataFrameDict),
                      columns=headers).sort_values(['Score'], ascending=[False])
我的目标是不使用循环或dict来进一步提高速度

我的函数ScoreAndCount返回每个玩家的分数和计数。concat获取该函数的返回值并将其添加到初始df中

然后,我使用了iTertools组合,并使其成为自己的数据框架,称为summary。然后,我将summary df的player1和player2列与原始df中的names列合并

接下来,我将球员的得分和计数相加,删除不必要的列,并进行排序。我的结果是每圈157ms。最慢的步骤是concat和merge,但我想不出绕过它们并进一步提高速度的方法

编辑3

我们将设置一个种子,并对两个测试使用相同的数据df:

np.random.seed(0)

player_list = ['player' + str(x) for x in range(1,71)]

data = pd.DataFrame({'Names': player_list*10,\
                    'Ob1' : np.random.rand(700),\
                    'Ob2' : np.random.rand(700) ,\
                    'Ob3' : np.random.rand(700)})

data.head()

      Names    Ob1         Ob2         Ob3
0   player1 0.548814    0.373216    0.313591
1   player2 0.715189    0.222864    0.365539
2   player3 0.602763    0.080532    0.201267
3   player4 0.544883    0.085311    0.487148
4   player5 0.423655    0.221396    0.990369
接下来,我们将使用您的确切代码,并检查player1和player2之间的dict


def points(row):
    val = 0
    if row['Ob2'] > 0.5:
        foo = row['Ob3'] - row['Ob1']
        if foo < 0.1:
            val = 1 - foo
    else:
        val = 0
    return val

#create list of unique pairs
comboNames = list(itertools.combinations(data.Names.unique(), 2))
DataFrameDict = {elem : pd.DataFrame for elem in comboNames}

for key in DataFrameDict.keys():
    DataFrameDict[key] = data[:][data.Names.isin(key)]
    DataFrameDict[key] = DataFrameDict[key].sort_values(['Ob1'])

#Add test calculated column
for tbl in DataFrameDict:
    DataFrameDict[tbl]['Test'] = DataFrameDict[tbl].apply(points, axis=1)

DataFrameDict[('player1', 'player2')].head()

     Names     Ob1        Ob2          Ob3     Test
351 player2 0.035362    0.013509    0.384273    0.0
630 player1 0.062636    0.305047    0.571550    0.0
561 player2 0.133461    0.758194    0.964210    0.0
211 player2 0.216897    0.056877    0.417333    0.0
631 player2 0.241902    0.557987    0.983555    0.0

data['test'] = np.where(data['Ob2'] > 0.5, np.where(data['Ob3'] - data['Ob1'] < 0.1, 1 - (data['Ob3'] - data['Ob1']), 0), 0)

def ScoreAndCount(row):
    score = row.sum()
    count = row.astype(bool).sum()
    return score, count

df = data.groupby('Names')['test'].apply(ScoreAndCount).reset_index()
df = pd.concat([df['Names'], df.test.apply(pd.Series).rename(columns = {0: 'Score', 1:'Count'})], axis = 1)

summary = pd.DataFrame(itertools.combinations(data.Names.unique(), 2), columns = ['Player1', 'Player2'])
summary = summary.merge(df, left_on = 'Player1', right_on = 'Names')\
                 .merge(df, left_on = 'Player2', right_on = 'Names')\
                 .drop(columns = ['Names_x', 'Names_y'])

summary['Score'] = summary['Score_x'] + summary['Score_y']
summary['Count'] = summary['Count_x'] + summary['Count_y']
summary.drop(columns = ['Score_x','Count_x', 'Score_y','Count_y'], inplace = True)
summary = summary.sort_values('Score', ascending = False)
最后我们得到了8.0774。现在,如果我说的是真的,如果我们在Edit2中使用我的代码,那么player1和player2之间的分数最终将为8.077


def points(row):
    val = 0
    if row['Ob2'] > 0.5:
        foo = row['Ob3'] - row['Ob1']
        if foo < 0.1:
            val = 1 - foo
    else:
        val = 0
    return val

#create list of unique pairs
comboNames = list(itertools.combinations(data.Names.unique(), 2))
DataFrameDict = {elem : pd.DataFrame for elem in comboNames}

for key in DataFrameDict.keys():
    DataFrameDict[key] = data[:][data.Names.isin(key)]
    DataFrameDict[key] = DataFrameDict[key].sort_values(['Ob1'])

#Add test calculated column
for tbl in DataFrameDict:
    DataFrameDict[tbl]['Test'] = DataFrameDict[tbl].apply(points, axis=1)

DataFrameDict[('player1', 'player2')].head()

     Names     Ob1        Ob2          Ob3     Test
351 player2 0.035362    0.013509    0.384273    0.0
630 player1 0.062636    0.305047    0.571550    0.0
561 player2 0.133461    0.758194    0.964210    0.0
211 player2 0.216897    0.056877    0.417333    0.0
631 player2 0.241902    0.557987    0.983555    0.0

data['test'] = np.where(data['Ob2'] > 0.5, np.where(data['Ob3'] - data['Ob1'] < 0.1, 1 - (data['Ob3'] - data['Ob1']), 0), 0)

def ScoreAndCount(row):
    score = row.sum()
    count = row.astype(bool).sum()
    return score, count

df = data.groupby('Names')['test'].apply(ScoreAndCount).reset_index()
df = pd.concat([df['Names'], df.test.apply(pd.Series).rename(columns = {0: 'Score', 1:'Count'})], axis = 1)

summary = pd.DataFrame(itertools.combinations(data.Names.unique(), 2), columns = ['Player1', 'Player2'])
summary = summary.merge(df, left_on = 'Player1', right_on = 'Names')\
                 .merge(df, left_on = 'Player2', right_on = 'Names')\
                 .drop(columns = ['Names_x', 'Names_y'])

summary['Score'] = summary['Score_x'] + summary['Score_y']
summary['Count'] = summary['Count_x'] + summary['Count_y']
summary.drop(columns = ['Score_x','Count_x', 'Score_y','Count_y'], inplace = True)
summary = summary.sort_values('Score', ascending = False)
如您所见,我从player1 player2到edit2计算的分数与您在代码中计算的分数完全相同

我的目标是不使用循环或dict来进一步提高速度

我的函数ScoreAndCount返回每个玩家的分数和计数。concat获取该函数的返回值并将其添加到初始df中

然后,我使用了iTertools组合,并使其成为自己的数据框架,称为summary。然后,我将summary df的player1和player2列与原始df中的names列合并

接下来,我将球员的得分和计数相加,删除不必要的列,并进行排序。我的结果是每圈157ms。最慢的步骤是concat和merge,但我想不出绕过它们并进一步提高速度的方法

编辑3

我们将设置一个种子,并对两个测试使用相同的数据df:

np.random.seed(0)

player_list = ['player' + str(x) for x in range(1,71)]

data = pd.DataFrame({'Names': player_list*10,\
                    'Ob1' : np.random.rand(700),\
                    'Ob2' : np.random.rand(700) ,\
                    'Ob3' : np.random.rand(700)})

data.head()

      Names    Ob1         Ob2         Ob3
0   player1 0.548814    0.373216    0.313591
1   player2 0.715189    0.222864    0.365539
2   player3 0.602763    0.080532    0.201267
3   player4 0.544883    0.085311    0.487148
4   player5 0.423655    0.221396    0.990369
接下来,我们将使用您的确切代码,并检查player1和player2之间的dict


def points(row):
    val = 0
    if row['Ob2'] > 0.5:
        foo = row['Ob3'] - row['Ob1']
        if foo < 0.1:
            val = 1 - foo
    else:
        val = 0
    return val

#create list of unique pairs
comboNames = list(itertools.combinations(data.Names.unique(), 2))
DataFrameDict = {elem : pd.DataFrame for elem in comboNames}

for key in DataFrameDict.keys():
    DataFrameDict[key] = data[:][data.Names.isin(key)]
    DataFrameDict[key] = DataFrameDict[key].sort_values(['Ob1'])

#Add test calculated column
for tbl in DataFrameDict:
    DataFrameDict[tbl]['Test'] = DataFrameDict[tbl].apply(points, axis=1)

DataFrameDict[('player1', 'player2')].head()

     Names     Ob1        Ob2          Ob3     Test
351 player2 0.035362    0.013509    0.384273    0.0
630 player1 0.062636    0.305047    0.571550    0.0
561 player2 0.133461    0.758194    0.964210    0.0
211 player2 0.216897    0.056877    0.417333    0.0
631 player2 0.241902    0.557987    0.983555    0.0

data['test'] = np.where(data['Ob2'] > 0.5, np.where(data['Ob3'] - data['Ob1'] < 0.1, 1 - (data['Ob3'] - data['Ob1']), 0), 0)

def ScoreAndCount(row):
    score = row.sum()
    count = row.astype(bool).sum()
    return score, count

df = data.groupby('Names')['test'].apply(ScoreAndCount).reset_index()
df = pd.concat([df['Names'], df.test.apply(pd.Series).rename(columns = {0: 'Score', 1:'Count'})], axis = 1)

summary = pd.DataFrame(itertools.combinations(data.Names.unique(), 2), columns = ['Player1', 'Player2'])
summary = summary.merge(df, left_on = 'Player1', right_on = 'Names')\
                 .merge(df, left_on = 'Player2', right_on = 'Names')\
                 .drop(columns = ['Names_x', 'Names_y'])

summary['Score'] = summary['Score_x'] + summary['Score_y']
summary['Count'] = summary['Count_x'] + summary['Count_y']
summary.drop(columns = ['Score_x','Count_x', 'Score_y','Count_y'], inplace = True)
summary = summary.sort_values('Score', ascending = False)
最后我们得到了8.0774。现在,如果我说的是真的,如果我们在Edit2中使用我的代码,那么player1和player2之间的分数最终将为8.077


def points(row):
    val = 0
    if row['Ob2'] > 0.5:
        foo = row['Ob3'] - row['Ob1']
        if foo < 0.1:
            val = 1 - foo
    else:
        val = 0
    return val

#create list of unique pairs
comboNames = list(itertools.combinations(data.Names.unique(), 2))
DataFrameDict = {elem : pd.DataFrame for elem in comboNames}

for key in DataFrameDict.keys():
    DataFrameDict[key] = data[:][data.Names.isin(key)]
    DataFrameDict[key] = DataFrameDict[key].sort_values(['Ob1'])

#Add test calculated column
for tbl in DataFrameDict:
    DataFrameDict[tbl]['Test'] = DataFrameDict[tbl].apply(points, axis=1)

DataFrameDict[('player1', 'player2')].head()

     Names     Ob1        Ob2          Ob3     Test
351 player2 0.035362    0.013509    0.384273    0.0
630 player1 0.062636    0.305047    0.571550    0.0
561 player2 0.133461    0.758194    0.964210    0.0
211 player2 0.216897    0.056877    0.417333    0.0
631 player2 0.241902    0.557987    0.983555    0.0

data['test'] = np.where(data['Ob2'] > 0.5, np.where(data['Ob3'] - data['Ob1'] < 0.1, 1 - (data['Ob3'] - data['Ob1']), 0), 0)

def ScoreAndCount(row):
    score = row.sum()
    count = row.astype(bool).sum()
    return score, count

df = data.groupby('Names')['test'].apply(ScoreAndCount).reset_index()
df = pd.concat([df['Names'], df.test.apply(pd.Series).rename(columns = {0: 'Score', 1:'Count'})], axis = 1)

summary = pd.DataFrame(itertools.combinations(data.Names.unique(), 2), columns = ['Player1', 'Player2'])
summary = summary.merge(df, left_on = 'Player1', right_on = 'Names')\
                 .merge(df, left_on = 'Player2', right_on = 'Names')\
                 .drop(columns = ['Names_x', 'Names_y'])

summary['Score'] = summary['Score_x'] + summary['Score_y']
summary['Count'] = summary['Count_x'] + summary['Count_y']
summary.drop(columns = ['Score_x','Count_x', 'Score_y','Count_y'], inplace = True)
summary = summary.sort_values('Score', ascending = False)

如您所见,我从player1 player2到我的edit2计算的分数与您在代码中计算的分数完全相同。

第6行到第14行的缩进没有缩小吗

def pointsrow: val=0 如果行['Ob2']>0.5: foo=行['Ob3']-行['Ob1'] 如果foo<0.1: val=1-foo 其他: val=0 返回值
第6行到第14行的缩进是否没有收缩

def pointsrow: val=0 如果行['Ob2']>0.5: foo=行['Ob3']-行['Ob1'] 如果foo<0.1: val=1-foo 其他: val=0 返回值
我可以用numba对你的函数进行矢量化,结果代码用%%timeit%%在8秒内运行。我听从了Ben Pap的建议,提前计算了测试柱。我还预先对值进行了排序,并整理了DataFrameDict创建

%%时间 作为pd进口熊猫 将numpy作为np导入 将datetime导入为日期 进口itertools 进口麻木 @矢量化 定义点A、b、c: val=0 如果b>0.5: foo=c-a 如果foo<0.1: val=1-foo 其他: val=0 返回值 player_list=['player'+范围1,71中x的strx] data=pd.DataFrame{'Names':播放器列表*1000\ “Ob1”:np.random.rand70000\ “Ob2”:np.random.rand70000\ 'Ob3':np.random.rand70000} 数据['Test']=pointsdata['Ob1']。值,数据['Ob2']。值,数据['Ob3']。值 data=data.sort_值['Ob1'] comboNames=ListItemTools.combinationsdata.Names.unique,2 DataFrameDict={elem:data.loc[data.Names.isinelem]表示comboNames中的元素} 页眉=['Player1'、'Player2'、'Score'、'Count'] summary=pd.DataFrame[tbl[0],tbl[1],DataFrameDict[tbl]['Test']]和, DataFrameDict[tbl]['Test'].astypebool.sumaxis=0]用于DataFrameDict中的tbl, 列=标题。排序_值['Score'],升序=[False] 每低8.52秒±204毫秒
op mean±标准偏差7次运行,每次循环1次

我能够使用numba对函数进行矢量化,并使用%%timeit在8秒内运行生成的代码。我听从了Ben Pap的建议,提前计算了测试柱。我还预先对值进行了排序,并整理了DataFrameDict创建

%%时间 作为pd进口熊猫 将numpy作为np导入 将datetime导入为日期 进口itertools 进口麻木 @矢量化 定义点A、b、c: val=0 如果b>0.5: foo=c-a 如果foo<0.1: val=1-foo 其他: val=0 返回值 player_list=['player'+范围1,71中x的strx] data=pd.DataFrame{'Names':播放器列表*1000\ “Ob1”:np.random.rand70000\ “Ob2”:np.random.rand70000\ 'Ob3':np.random.rand70000} 数据['Test']=pointsdata['Ob1']。值,数据['Ob2']。值,数据['Ob3']。值 data=data.sort_值['Ob1'] comboNames=ListItemTools.combinationsdata.Names.unique,2 DataFrameDict={elem:data.loc[data.Names.isinelem]表示comboNames中的元素} 页眉=['Player1'、'Player2'、'Score'、'Count'] summary=pd.DataFrame[tbl[0],tbl[1],DataFrameDict[tbl]['Test']]和, DataFrameDict[tbl]['Test'].astypebool.sumaxis=0]用于DataFrameDict中的tbl, 列=标题。排序_值['Score'],升序=[False] 8.52 s±204 ms/循环7次运行的平均值±标准偏差,每个循环1次

我重点关注调用apply的功能点和for循环

功能点可以转换为此条件a_df是DataFrameDict中的每个数据帧:

这个跑得相当快

输出:DataFrameDict的每个DataFrame都根据指定的条件填充了测试列。我从DataFrameDict中随机选取一个最终数据帧来显示输出

In [1288]: DataFrameDict[('player65', 'player67')]
Out[1288]:
          Names       Ob1       Ob2       Ob3      Test
61456  player67  0.000271  0.686051  0.729086  0.000000
25824  player65  0.001281  0.505552  0.296550  0.000000
25544  player65  0.001398  0.770805  0.471477  0.000000
65864  player65  0.001999  0.147407  0.291841  0.000000
33104  player65  0.002661  0.254329  0.126290  0.000000
42554  player65  0.003172  0.529603  0.181796  0.000000
28064  player65  0.003663  0.227429  0.558233  0.000000
24844  player65  0.005517  0.096817  0.710771  0.000000
2584   player65  0.005974  0.338904  0.582034  0.000000
42694  player65  0.005996  0.171637  0.765277  0.000000
6154   player65  0.006126  0.181239  0.295149  0.000000
65234  player65  0.008386  0.180613  0.994273  0.000000
5034   player65  0.008921  0.013060  0.305063  0.000000
21766  player67  0.010950  0.590966  0.481547  0.000000
53054  player65  0.010957  0.731794  0.262754  0.000000
15956  player67  0.010996  0.046718  0.153172  0.000000
36046  player67  0.011634  0.250039  0.064184  0.000000
50394  player65  0.011835  0.995986  0.834281  0.000000
64326  player67  0.011974  0.499262  0.745194  0.000000
30236  player67  0.013029  0.101714  0.143509  0.000000
23374  player65  0.014865  0.158185  0.575582  0.000000
1256   player67  0.014915  0.938301  0.629850  0.000000
10216  player67  0.015122  0.450750  0.137085  0.000000
21904  player65  0.016372  0.147897  0.786882  0.000000
34854  player65  0.016603  0.513692  0.676243  0.000000
33806  player67  0.016820  0.063896  0.577731  0.000000
29816  player67  0.017565  0.060496  0.151780  0.000000
6924   player65  0.017652  0.121581  0.117512  0.000000
39126  player67  0.017990  0.516819  0.663672  0.000000
39896  player67  0.018085  0.031526  0.075832  0.000000
...         ...       ...       ...       ...       ...
61526  player67  0.985386  0.512073  0.754241  1.231145
48926  player67  0.985504  0.007080  0.671456  0.000000
16234  player65  0.985775  0.846647  0.998181  0.000000
12736  player67  0.985846  0.283997  0.667314  0.000000
47874  player65  0.986084  0.052026  0.508918  0.000000
29886  player67  0.986655  0.998440  0.068136  1.918518
49416  player67  0.986706  0.833053  0.182814  1.803892
42486  player67  0.986797  0.608128  0.136219  1.850578
55644  player65  0.987796  0.215898  0.561002  0.000000
1814   player65  0.987935  0.324954  0.525433  0.000000
7554   player65  0.988910  0.664914  0.674546  1.314365
59774  player65  0.989147  0.235214  0.913588  0.000000
58444  player65  0.989467  0.645191  0.533468  1.455999
62856  player67  0.989470  0.523544  0.302838  1.686632
48646  player67  0.990588  0.522521  0.201132  1.789456
11336  player67  0.990629  0.932360  0.756544  1.234085
31774  player65  0.990881  0.981641  0.943824  1.047057
18964  player65  0.992287  0.808989  0.948321  1.043967
14486  player67  0.992909  0.437701  0.484678  0.000000
12246  player67  0.994027  0.542903  0.234830  1.759197
33596  player67  0.994257  0.949055  0.098368  1.895889
6436   player67  0.994661  0.444211  0.572136  0.000000
4194   player65  0.995022  0.721113  0.584195  1.410826
42696  player67  0.995065  0.516103  0.918737  1.076328
51026  player67  0.995864  0.877335  0.516737  1.479127
14136  player67  0.997691  0.134021  0.913969  0.000000
47664  player65  0.998051  0.628051  0.722695  1.275357
55924  player65  0.998079  0.828749  0.151217  1.846863
18474  player65  0.998780  0.200990  0.098713  0.000000
41296  player67  0.998884  0.167139  0.504899  0.000000

[2000 rows x 5 columns]
我主要关注函数点和调用apply的for循环

功能点可以转换为此条件a_df是DataFrameDict中的每个数据帧:

这个跑得相当快

输出:DataFrameDict的每个DataFrame都根据指定的条件填充了测试列。我从DataFrameDict中随机选取一个最终数据帧来显示输出

In [1288]: DataFrameDict[('player65', 'player67')]
Out[1288]:
          Names       Ob1       Ob2       Ob3      Test
61456  player67  0.000271  0.686051  0.729086  0.000000
25824  player65  0.001281  0.505552  0.296550  0.000000
25544  player65  0.001398  0.770805  0.471477  0.000000
65864  player65  0.001999  0.147407  0.291841  0.000000
33104  player65  0.002661  0.254329  0.126290  0.000000
42554  player65  0.003172  0.529603  0.181796  0.000000
28064  player65  0.003663  0.227429  0.558233  0.000000
24844  player65  0.005517  0.096817  0.710771  0.000000
2584   player65  0.005974  0.338904  0.582034  0.000000
42694  player65  0.005996  0.171637  0.765277  0.000000
6154   player65  0.006126  0.181239  0.295149  0.000000
65234  player65  0.008386  0.180613  0.994273  0.000000
5034   player65  0.008921  0.013060  0.305063  0.000000
21766  player67  0.010950  0.590966  0.481547  0.000000
53054  player65  0.010957  0.731794  0.262754  0.000000
15956  player67  0.010996  0.046718  0.153172  0.000000
36046  player67  0.011634  0.250039  0.064184  0.000000
50394  player65  0.011835  0.995986  0.834281  0.000000
64326  player67  0.011974  0.499262  0.745194  0.000000
30236  player67  0.013029  0.101714  0.143509  0.000000
23374  player65  0.014865  0.158185  0.575582  0.000000
1256   player67  0.014915  0.938301  0.629850  0.000000
10216  player67  0.015122  0.450750  0.137085  0.000000
21904  player65  0.016372  0.147897  0.786882  0.000000
34854  player65  0.016603  0.513692  0.676243  0.000000
33806  player67  0.016820  0.063896  0.577731  0.000000
29816  player67  0.017565  0.060496  0.151780  0.000000
6924   player65  0.017652  0.121581  0.117512  0.000000
39126  player67  0.017990  0.516819  0.663672  0.000000
39896  player67  0.018085  0.031526  0.075832  0.000000
...         ...       ...       ...       ...       ...
61526  player67  0.985386  0.512073  0.754241  1.231145
48926  player67  0.985504  0.007080  0.671456  0.000000
16234  player65  0.985775  0.846647  0.998181  0.000000
12736  player67  0.985846  0.283997  0.667314  0.000000
47874  player65  0.986084  0.052026  0.508918  0.000000
29886  player67  0.986655  0.998440  0.068136  1.918518
49416  player67  0.986706  0.833053  0.182814  1.803892
42486  player67  0.986797  0.608128  0.136219  1.850578
55644  player65  0.987796  0.215898  0.561002  0.000000
1814   player65  0.987935  0.324954  0.525433  0.000000
7554   player65  0.988910  0.664914  0.674546  1.314365
59774  player65  0.989147  0.235214  0.913588  0.000000
58444  player65  0.989467  0.645191  0.533468  1.455999
62856  player67  0.989470  0.523544  0.302838  1.686632
48646  player67  0.990588  0.522521  0.201132  1.789456
11336  player67  0.990629  0.932360  0.756544  1.234085
31774  player65  0.990881  0.981641  0.943824  1.047057
18964  player65  0.992287  0.808989  0.948321  1.043967
14486  player67  0.992909  0.437701  0.484678  0.000000
12246  player67  0.994027  0.542903  0.234830  1.759197
33596  player67  0.994257  0.949055  0.098368  1.895889
6436   player67  0.994661  0.444211  0.572136  0.000000
4194   player65  0.995022  0.721113  0.584195  1.410826
42696  player67  0.995065  0.516103  0.918737  1.076328
51026  player67  0.995864  0.877335  0.516737  1.479127
14136  player67  0.997691  0.134021  0.913969  0.000000
47664  player65  0.998051  0.628051  0.722695  1.275357
55924  player65  0.998079  0.828749  0.151217  1.846863
18474  player65  0.998780  0.200990  0.098713  0.000000
41296  player67  0.998884  0.167139  0.504899  0.000000

[2000 rows x 5 columns]

部分受@andy的回答影响,谢谢。与我的Edit2代码相比,大大减少了运行时间

删除func并使用np进行所有计算。其中:

作为pd进口熊猫 将numpy作为np导入 将datetime导入为日期 进口itertools def random_datesstart,end,n,unit='D',seed=None: 如果不是种子: np.random.0 ndays=结束-开始。天数+1 返回pd.to_timedeltanp.random.randn*ndays,单位=单位+开始 打印开始:+strdate.datetime.now 打印 player_list=['player'+范围1,71中x的strx] np.random.0 开始=pd.至日期时间'2019-04-01' 结束=截止日期时间2019-04-10的pd data=pd.DataFrame{'Names':播放器列表*1000, “日期”:随机\u日期开始,结束,70000} 创建唯一对的列表 comboNames=ListItemTools.combinationsdata.Names.unique,2 创建数据帧字典以存储数据帧 DataFrameDict={elem:pd.DataFrame for comboNames中的元素} 对于DataFrameDict.keys中的键: DataFrameDict[key]=data[:][data.Names.isinkey] DataFrameDict[key]=DataFrameDict[key]。排序值['Dates'] 秒=DataFrameDict[key][Dates']-DataFrameDict[key]['Dates'].shift1/np.timedelta641,'s' DataFrameDict[key]['Test']=np。其中DataFrameDict[key]['Names'!=DataFrameDict[key]['Names'].shift1&\
np.logical_and seconds>=1,seconds部分受@andy的回答影响,谢谢。与我的Edit2代码相比,大大减少了运行时间

删除func并使用np进行所有计算。其中:

作为pd进口熊猫 将numpy作为np导入 将datetime导入为日期 进口itertools def random_datesstart,end,n,unit='D',seed=None: 如果不是种子: np.random.0 ndays=结束-开始。天数+1 返回pd.to_timedeltanp.random.randn*ndays,单位=单位+开始 打印开始:+strdate.datetime.now 打印 player_list=['player'+范围1,71中x的strx] np.random.0 开始=pd.至日期时间'2019-04-01' 结束=截止日期时间2019-04-10的pd data=pd.DataFrame{'Names':播放器列表*1000, “日期”:随机\u日期开始,结束,70000} 创建唯一对的列表 comboNames=ListItemTools.combinationsdata.Names.unique,2 创建数据帧字典以存储数据帧 DataFrameDict={elem:pd.DataFrame for comboNames中的元素} 对于DataFrameDict.keys中的键: DataFrameDict[key]=data[:][data.Names.isinkey] DataFrameDict[key]=DataFrameDict[key]。排序值['Dates'] 秒=DataFrameDict[key][Dates']-DataFrameDict[key]['Dates'].shift1/np.timedelta641,'s' DataFrameDict[key]['Test']=np。其中DataFrameDict[key]['Names'!=DataFrameDict[key]['Names'].shift1&\
np.logical_and seconds>=1,seconds什么是播放器列表对不起,当

邮寄。感谢您的提醒您在DataFrameDict中使用tbl有什么原因吗:DataFrameDict[tbl]['Test']=DataFrameDict[tbl].applypoints,axis=1创建dict后?您的函数不关心它是用于dict键player1、player3还是player1、player2,因为player1行不受其他播放器的影响。换句话说,在原始df而不是每个dict键上执行应用程序可以节省大量时间。您好@Ben,是的,在上面的工作示例中,可能没有明显的原因。基本上,该函数添加了一个列,用于比较每个df中的两个玩家,因此我们/我无法将其应用于源df。抱歉没有说得更清楚,并感谢下面的输入。什么是player_list对不起,发帖时错过了那一行。感谢您的提醒您在DataFrameDict中使用tbl有什么原因吗:DataFrameDict[tbl]['Test']=DataFrameDict[tbl].applypoints,axis=1创建dict后?您的函数不关心它是用于dict键player1、player3还是player1、player2,因为player1行不受其他播放器的影响。换句话说,在原始df而不是每个dict键上执行应用程序可以节省大量时间。您好@Ben,是的,在上面的工作示例中,可能没有明显的原因。基本上,该函数添加了一个列,用于比较每个df中的两个玩家,因此我们/我无法将其应用于源df。抱歉没有说得更清楚,谢谢你在下面的输入。请注意,所有到Stack Overflow的帖子都必须是英文的。使用“编辑”按钮更新您的答案并查看详细信息。这是因为我没有在此处正确地按ctrl+K键缩进代码,在实际代码中,代码缩进正确。请注意,Stack Overflow的所有帖子都必须使用英语。使用“编辑”按钮更新您的答案并查看详细信息。这是因为我没有按ctrl+K键正确缩进此处的代码,在实际代码中,代码缩进正确。我尝试优化函数时非常相似,只是我从numba导入了jit并使用了@jit,还忘记了DataFrameDict[tbl]['Test']中的=pointsDataFrameDict[tbl]['Ob1']。值,\。。。根据我对Ben的评论,您在保持for循环的同时,将运行时间减少到了29秒,这是一个很大的改进!我优化函数的尝试非常相似,只是我从numba导入了jit并使用了@jit,还忘记了DataFrameDict[tbl]['Test']=pointsDataFrameDict[tbl]['Ob1']中的.value。value,\。。。根据我对Ben的评论,您在保持for循环的同时,将运行时间减少到了29秒,这是一个很大的改进!你的编辑很有趣。我确实记得,我认为这一定是一种绕过数据帧的Dict,只从源df提取结果聚合的方法。考虑到我的要求,我需要计算每个组合的得分,每个子df,你认为这可以实现吗?也就是说,测试列不适用于数据,但在playerX vs.playerYSo的合并中的某个地方,在原始代码中,您计算两个播放器的测试列之和。例如,在player1对player2和player1对player3中,每一行的第一行都是完全相同的player1行。我在编辑中所做的是在迭代之前获取个体的总和,因为这没有任何区别。在迭代之后,我将单个测试的和加在一起,得到总和。这可以在摘要['Score']=摘要['Score_x']+摘要['Score_y']中看到。分数x和分数y是单独的总分测试,当总分达到你想要的分数时,请查看我对问题的编辑或我对主要问题的评论。每个数据帧都是一对数据的比较。因此,为了澄清,测试列必须添加到每个df中,因为它实际上是playX和playerY属性之间的比较。在我的示例代码中,我创建了一个操作类似但不完全相同的函数,这意味着区别不是很明显,这是我的错,所以很抱歉。但是您代码的目标是总结df,不是吗?口述只是一种中间产物。如果玩家之间的口述是你的目标,那么这是一个不同的问题,然而,我的工作假设摘要df是你的目标,因此我的第二个编辑代码应该以不同的方法为你提供与原始代码完全相同的答案。最终目标是摘要是,但“测试”列不能应用于数据df,它必须应用于每个玩家v玩家子df。如果我能用你编辑的有趣的源df‘数据’计算分数,我就不会费心创建df的字典了。我确实记得,我认为这一定是一种绕过数据帧的Dict,只从源df提取结果聚合的方法。考虑到我的要求,我需要计算每个组合的得分,每个子df,你认为这可以实现吗?即,测试列不适用于数据,但在pla合并中的某个位置
yerX vs.playerYSo在原始代码中,计算两个玩家的测试列之和。例如,在player1对player2和player1对player3中,每一行的第一行都是完全相同的player1行。我在编辑中所做的是在迭代之前获取个体的总和,因为这没有任何区别。在迭代之后,我将单个测试的和加在一起,得到总和。这可以在摘要['Score']=摘要['Score_x']+摘要['Score_y']中看到。分数x和分数y是单独的总分测试,当总分达到你想要的分数时,请查看我对问题的编辑或我对主要问题的评论。每个数据帧都是一对数据的比较。因此,为了澄清,测试列必须添加到每个df中,因为它实际上是playX和playerY属性之间的比较。在我的示例代码中,我创建了一个操作类似但不完全相同的函数,这意味着区别不是很明显,这是我的错,所以很抱歉。但是您代码的目标是总结df,不是吗?口述只是一种中间产物。如果玩家之间的口述是你的目标,那么这是一个不同的问题,然而,我的工作假设摘要df是你的目标,因此我的第二个编辑代码应该以不同的方法为你提供与原始代码完全相同的答案。最终目标是摘要是,但“测试”列不能应用于数据df,它必须应用于每个玩家v玩家子df。如果我可以使用源df“数据”计算分数,我就不会费心创建df的字典了。我喜欢它,对我来说,它比使用func看起来更整洁,而且我还学会了一些使用df的方法。可惜它比@Cr1064的矢量化慢2倍;我喜欢它,对我来说,它比使用func看起来更整洁,我也学到了一些关于使用df的知识。可惜它比@Cr1064的矢量化慢2倍;