Pandas Efficient计算列中的唯一值,然后查找该计数的最大值

时间:2016-03-01 13:05:34

标签: python pandas

数据框(df)如下所示:

    Date                Caller  Called
0   2011-01-01 00:00:00 Sarah   Claire
1   2011-01-01 00:00:00 Sarah   Ryan
2   2011-01-01 00:00:00 Sarah   Alex
3   2011-01-02 00:00:00 Sarah   Max
4   2011-01-02 00:00:00 Sarah   Phoebe


number_date =  df.groupby(['Caller',pd.DatetimeIndex(df['Date']).normalize()])
number_date['Called'].unique().apply(lambda x: len(x))

这符合我的期望。她在第一场打了3个电话,在第二场打了两场电话:

Caller            
Sarah   2011-01-01    3
        2011-01-02    2

如何将其修改为:

Caller   MaxCallsOneDay
Sarah    3

2 个答案:

答案 0 :(得分:1)

您可以尝试nuniquenlargest

print df
        Date  Caller  Called
0 2011-01-01   Sarah  Claire
1 2011-01-01   Sarah    Ryan
2 2011-01-01  Sarah1    Ryan
3 2011-01-01  Sarah1   Ryan1
4 2011-01-01  Sarah1    Ryan
5 2011-01-01   Sarah    Alex
6 2011-01-02   Sarah     Max

number_date=df.groupby(['Caller',pd.DatetimeIndex(df['Date']).normalize()])['Called'].nunique()
              .groupby(level=0).nlargest(1).reset_index(level=1, drop=True).reset_index()

number_date.columns = ['Caller','Date', 'MaxCallsOneDay']
print number_date
   Caller       Date  MaxCallsOneDay
0   Sarah 2011-01-01               3
1  Sarah1 2011-01-01               2

如果您不需要列Date,请使用max

df = df.groupby(['Caller',pd.DatetimeIndex(df['Date']).normalize()])['Called'].nunique()
       .groupby(level=0).max().reset_index(name='MaxCallsOneDay')
print df
   Caller  MaxCallsOneDay
0   Sarah               3
1  Sarah1               2

计时 - len(df) = 7k

In [531]: %timeit df.groupby(['Caller',pd.DatetimeIndex(df['Date']).normalize()])['Called'].unique().apply(lambda x: len(x)).groupby(level=0).nlargest(1).reset_index(level=1, drop=True).reset_index()
The slowest run took 4.80 times longer than the fastest. This could mean that an intermediate result is being cached 
10 loops, best of 3: 8.58 ms per loop

In [532]: %timeit df.groupby(['Caller',pd.DatetimeIndex(df['Date']).normalize()])['Called'].nunique().groupby(level=0).nlargest(1).reset_index(level=1, drop=True).reset_index()
100 loops, best of 3: 7.07 ms per loop

In [547]: %timeit df.groupby(['Caller',pd.DatetimeIndex(df['Date']).normalize()])['Called'].nunique().groupby(level=0).max().reset_index(name='MaxCallsOneDay')
100 loops, best of 3: 3.52 ms per loop

答案 1 :(得分:0)

再次对现有数据框进行分组,使用level=[0]指定分组索引中的第一个级别(即调用方):

# existing dataframe
df = pd.DataFrame(
    {'Called': ['Claire', 'Ryan', 'Ryan', 'Ryan1', 'Ryan', 'Alex', 'Max'],
     'Caller': ['Sarah', 'Sarah', 'John', 'John', 'John', 'Sarah', 'Sarah'],
     'Date': ['2011-01-01'] * 6 + ['2011-01-02']})

# Group on dataframe.
gb = df.groupby(['Caller', pd.DatetimeIndex(df['Date']).normalize()]).Called.count()

>>> gb.groupby(level=[0]).max()
Caller
John     3
Sarah    3
Name: Called, dtype: int64