Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/291.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 提高重复分组操作的性能_Python_Pandas_Numpy - Fatal编程技术网

Python 提高重复分组操作的性能

Python 提高重复分组操作的性能,python,pandas,numpy,Python,Pandas,Numpy,我有一个带有多索引的数据帧,它基本上是一个二进制矩阵: day day01 day02 session session1 session2 session3 session1 session2 session3 0 1 0 0 0 0 0 1 0 0 1

我有一个带有多索引的数据帧,它基本上是一个二进制矩阵:

day        day01                      day02                  
session session1 session2 session3 session1 session2 session3
0              1        0        0        0        0        0
1              0        0        1        1        1        0
2              1        1        1        0        0        1
3              1        0        0        1        0        0
4              1        0        1        0        0        0
从这个数据框中,我需要计算每行的每日总和:

     day01  day02
0        1      0
1        1      2
2        3      1
3        1      1
4        2      0
         session1  session2  session3
0               1         0         0
1               1         1         1
2               1         1         2
3               2         0         0
4               1         0         1
并获取0、1的数量。。。(值计数)在此总和中:

0    2
1    5
2    2
3    1
我也需要为会议做这个。每行的会话总数:

     day01  day02
0        1      0
1        1      2
2        3      1
3        1      1
4        2      0
         session1  session2  session3
0               1         0         0
1               1         1         1
2               1         1         2
3               2         0         0
4               1         0         1
并获取值计数:

0    5
1    8
2    2
作为基线,这是df.groupby(level='day',axis=1.sum().stack().value_counts()(和
df.groupby(level='session',axis=1.sum().stack().value_counts()
)的结果。数据帧在模拟退火算法的每次迭代中发生变化,并重新计算这些计数。当我分析代码时,我发现在groupby操作上花费了大量时间

我试着保存groupby对象,并在每次迭代中对这些对象求和,但改进了大约10%。下面是创建更大数据帧的代码(类似于我的代码):

在我的计算机中,以下两种方法分别需要3.8s和3.38s

def try1(df, num_repeats=1000):
    for i in range(num_repeats):
        session_counts = (df.groupby(level='session', axis=1, sort=False)
                            .sum()
                            .stack()
                            .value_counts(sort=False))
        daily_counts = (df.groupby(level='day', axis=1, sort=False)
                          .sum()
                          .stack()
                          .value_counts(sort=False))
    return session_counts, daily_counts

def try2(df, num_repeats=1000):
    session_groups = df.groupby(level='session', axis=1, sort=False)
    day_groups = df.groupby(level='day', axis=1, sort=False)
    for i in range(num_repeats):
        df.iat[0, 0] = (i + 1) % 2
        session_counts = session_groups.sum().stack().value_counts(sort=False)
        daily_counts = day_groups.sum().stack().value_counts(sort=False)
    return session_counts, daily_counts

%time try1(df)
Wall time: 3.8 s

%time try2(df)
Wall time: 3.38 s
注意:函数中的循环仅用于计时。对于第二个函数,为了获得正确的计时,我需要修改数据帧

我目前正在研究另一种方法,在不重新计算组的情况下,直接将数据帧中的更改反映到计数,但我还没有成功。跟踪受影响的行和更新保存的数据帧的速度变慢了


有没有办法提高这些groupby操作的性能

假设采用常规数据格式(每行的天数和会话数相等),下面是一种基于NumPy的方法,使用
np.unique
,输出的索引按排序顺序排列-

# Extract array
a,b = df.columns.levels
arr = df.values.reshape(-1,len(a),len(b))

# Get session counts
session_sums = arr.sum(1)
unq,count = np.unique(session_sums,return_counts=True)
session_counts_out = pd.Series(count,index=unq)

# Get daily count
daily_sums = arr.sum(2)
unq,count = np.unique(daily_sums,return_counts=True)
daily_counts_out = pd.Series(count,index=unq)
如果您只对没有索引的值感兴趣,那么这里有一个使用
np.bincount
的替代方法,它基本上只进行计数,就像
return\u counts
part with
np.unique
-

# Get session counts
session_sums = arr.sum(1)
count = np.bincount(session_sums.ravel())
session_counts_out = count[count>0]

# Get daily count
daily_sums = arr.sum(2)
count = np.bincount(daily_sums.ravel())
daily_counts_out = count[count>0]

两个输出中元素的顺序重要吗?另外,两个输出的索引是否重要?不,只要我知道其中有多少个0、1等,顺序(或哪个数据结构保存该信息)就不重要。我应该知道哪个对应0,哪个对应1。谢谢。看起来很有希望。让我试试。bincount大约比groupby快7倍(我删除了
count[count>0]
的部分,以便通过索引访问)。让我把它打开几天,看看是否还有其他选择。再次感谢您。使用np.bincount是一种非常反模式的方法-它只在非常有限的输入集上有效,并且不进行任何转换;你在强迫用户做这么多事情work@Jeff如果你说的是非常有限的输入集,你指的是数字,是的,它只指数字。但好的一面是表现。我想这是一个用户可以决定的权衡<代码>np。如第一种方法所述,unique始终作为良好的备份存在。来投票吧@杰夫:是的,我不知道如何在这种情况下使用
pd.unique
。为什么不把它作为一个答案,我们可以计时呢?