Python 带有.agg()的数据帧多操作的进度条

Python 带有.agg()的数据帧多操作的进度条,python,pandas,tqdm,Python,Pandas,Tqdm,我想对一个巨大的数据集应用.agg操作 例如,我有以下代码: from tqdm import tqdm import pandas as pd df = pd.DataFrame({"A":[1.0, 2.0, 3.0, 1.0, 2.0, 3.0, 1.0, 2.0, 3.0], "B":[1.0, 1.0, 1.0, 2.0, 2.0, 2.0, 3.0, 3.0, 3.0], "C":[1.0, 1.5, 2

我想对一个巨大的数据集应用.agg操作

例如,我有以下代码:

from tqdm import tqdm
import pandas as pd
df = pd.DataFrame({"A":[1.0, 2.0, 3.0, 1.0, 2.0, 3.0, 1.0, 2.0, 3.0], 
                   "B":[1.0, 1.0, 1.0, 2.0, 2.0, 2.0, 3.0, 3.0, 3.0], 
                   "C":[1.0, 1.5, 2.0, 2.0, 3.0, 4.0, 5.0, 6.0, 10.0],
                   "D":[2.0, 5.0, 3.0, 6.0, 4.0, 2.0, 5.0, 1.0, 2.0],
                   "E":['a', 'a', 'b', 'a', 'b', 'b', 'b', 'a', 'a']}) 

df2 = df.groupby('B').agg({
                           'C': 'mean',
                           'D': 'sum',
                           'E': lambda x: x.mode()
                         })
print(df2)
问题是我的原始数据集有2.000.000行。将其转换为130.000需要几分钟,我希望看到一个进度条


我尝试过
tqdm
,但我不知道如何在这里应用它。是否有任何类似于
.progress\u apply()
的函数,但对于
.agg()

这将在运行时打印进度,其中进度由计算统计数据的组的分数来衡量。但我不确定这个循环会让你的计算慢多少

agger = {
   'C': 'mean',
   'D': 'sum',
   'E': lambda x: x.mode()}


gcols = ['B'] # columns defining the groups
groupby = df.groupby(gcols)

ngroups = len(groupby)
gfrac = 0.3 # fraction of groups for which you want to print progress
gfrac_size = max((1, int(ngroups*gfrac)))
groups = []
rows = []
for i,g in enumerate(groupby):

    if (i+1)%gfrac_size == 0:
        print('{:.0f}% complete'.format(100*(i/ngroups)))

    gstats = g[1].agg(agger)
    if i==0:
        if gstats.ndim==2:
            newcols = gstats.columns.tolist()
        else:
            newcols = gstats.index.tolist()

    groups.append(g[0])
    rows.append(gstats.values.flat)

df3 = pd.DataFrame(np.vstack(rows), columns=newcols)
if len(gcols) == 1:
    df3.index = groups
else:
    df3.index = pd.MultiIndex.from_tuples(groups, names=gcols)
df3 = df3.astype(df[newcols].dtypes)
df3
       C     D  E
1.0  1.5  10.0  a
2.0  3.0  12.0  b
3.0  7.0   8.0  a
另一种方法(尽管有点老套)是利用您使用自己的函数
lambda x:x.mode
这一事实。由于使用此函数已经降低了速度,因此可以编写一个类来存储有关进度的信息。比如说,

import pandas as pd
import numpy as np
df = pd.DataFrame({"A":[1.0, 2.0, 3.0, 1.0, 2.0, 3.0, 1.0, 2.0, 3.0], 
                   "B":[1.0, 1.0, 1.0, 2.0, 2.0, 2.0, 3.0, 3.0, 3.0], 
                   "C":[1.0, 1.5, 2.0, 2.0, 3.0, 4.0, 5.0, 6.0, 10.0],
                   "D":[2.0, 5.0, 3.0, 6.0, 4.0, 2.0, 5.0, 1.0, 2.0],
                   "E":['a', 'a', 'b', 'a', 'b', 'b', 'b', 'a', 'a']}) 

df2 = df.groupby('B').agg({
                           'C': 'mean',
                           'D': 'sum',
                           'E': lambda x: x.mode()
                         })
print(df2)

class ModeHack:

    def __init__(self, size=5, N=10):
        self.ix = 0
        self.K = 1 
        self.size = size
        self.N = N

    def mode(self, x):
        self.ix = self.ix + x.shape[0]
        if self.K*self.size <= self.ix:
            print('{:.0f}% complete'.format(100*self.ix/self.N))
            self.K += 1

        return x.mode()

    def reset(self):    
        self.ix = 0
        self.K = 1

mymode = ModeHack(size=int(.1*df.shape[0]), N=df.shape[0])
mymode.reset()

agger = {
   'C': 'mean',
   'D': 'sum',
   'E': lambda x: mymode.mode(x)}

df3 = df.groupby('B').agg(agger)
将熊猫作为pd导入
将numpy作为np导入
df=pd.DataFrame({“A”:[1.0,2.0,3.0,1.0,2.0,3.0,1.0,2.0,3.0],
“B”:[1.0,1.0,1.0,2.0,2.0,2.0,3.0,3.0,3.0],
“C”:[1.0,1.5,2.0,2.0,3.0,4.0,5.0,6.0,10.0],
“D”:[2.0,5.0,3.0,6.0,4.0,2.0,5.0,1.0,2.0],
“E”:[‘a’、‘a’、‘b’、‘a’、‘b’、‘b’、‘a’、‘a’]]
df2=df.groupby('B').agg({
‘C’:‘平均’,
‘D’:‘sum’,
“E”:lambda x:x.mode()
})
打印(df2)
类别ModeHack:
def uuu init uuuu(self,size=5,N=10):
self.ix=0
self.K=1
self.size=大小
self.N=N
def模式(自我,x):
self.ix=self.ix+x.shape[0]

如果self.K*self.size我以前见过,但我对此无能为力。我不需要使用apply()应用简单的操作。相反,我需要用agg()应用几个操作,因为这个例子非常好,呵呵,但是如何在用两列而不是一列过滤的数据帧中应用相同的操作呢
df.B.nunique
仅对一列有效……我刚刚修改了它,以便从groupby对象中获得组数。因此,如果您更改为df.groupby(['A','B']),那么在您的示例中会得到9。再次修改以允许groupby语句中有多个列。这是一个非常好的尝试,但它大大延长了计算时间。我想以一种有效的方式做这件事是不可能的。我使用
tqdm
pack改进了您的代码。它有一个更友好的显示。非常感谢您抽出时间。