Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.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 从groupby返回列表的最有效方法_Python_List_Pandas_Dataframe_Grouping - Fatal编程技术网

Python 从groupby返回列表的最有效方法

Python 从groupby返回列表的最有效方法,python,list,pandas,dataframe,grouping,Python,List,Pandas,Dataframe,Grouping,我有一个130M行数据帧,下面是一个示例: id id2 date value 0 33208381500016 1927637 2014-07-31 120.0 1 77874276700016 3418498 2014-11-22 10.5 2 77874276700016 1174018 2014-11-22 8.4 3 77874276700016 1174018 2014-11-20 1.

我有一个130M行数据帧,下面是一个示例:

    id              id2     date         value
0   33208381500016  1927637 2014-07-31   120.0
1   77874276700016  3418498 2014-11-22   10.5
2   77874276700016  1174018 2014-11-22   8.4
3   77874276700016  1174018 2014-11-20   1.4
4   77874276700016  1643839 2014-06-27   4.2
5   77874276700016  1972929 2014-06-27   6.7
6   77874276700016  1972929 2014-06-27   12.7
7   77874276700016  1588191 2014-02-20   123.4
8   77874276700016  1966627 2014-02-20   973.1
9   77874276700016  1830252 2014-02-20   0.5
我需要在此数据帧上执行
groupby
(称为
data
)。对于简单的
groupby
sum
没有问题:

data[['id','value']].groupby('id',as_index=False).sum()
time: 11.19s
但现在我需要检索另一列中的值列表(或其长度)。下面的代码可以工作,但需要很长时间,有没有更有效的方法

temp = data[['id','date','id2']].drop_duplicates()
temp.groupby('id',as_index = False).agg({'date': lambda x: set(x.tolist()),'id2':lambda x: len(set(x.tolist()))})
time: 159s
第一个问题:

是否有更有效的方法来计算每个
id
的唯一
id2
的数量,但仍使用此groupby?我的意思是,我不想拆分两个groupby,因为这可能需要更长的时间(使用两个聚合执行一个groupby大约需要1.5倍的时间)

第二个问题:


是否有更有效的方法检索唯一日期列表?我知道它已经在中解决了,但我不能简单地使用
。应用(列表)

要获得唯一的日期,请使用。要计算每组中唯一的
id2
的数量,请使用

事先不删除重复项可能会更快—pandas只需在所有数据上迭代一次,而不是两次

data.groupby('id', as_index=False).agg({'date': 'unique', 'id2': 'nunique'})
编辑:

以下是一些基准。有趣的是,
SeriesGroupBy.unique()
SeriesGroupBy.nunique()
似乎并不比使用集合更快。但之前不删除重复项是很重要的

import io

import pandas as pd

raw = io.StringIO("""\
id              id2     date         value
0   33208381500016  1927637 2014-07-31   120.0
1   77874276700016  3418498 2014-11-22   10.5
2   77874276700016  1174018 2014-11-22   8.4
3   77874276700016  1174018 2014-11-20   1.4
4   77874276700016  1643839 2014-06-27   4.2
5   77874276700016  1972929 2014-06-27   6.7
6   77874276700016  1972929 2014-06-27   12.7
7   77874276700016  1588191 2014-02-20   123.4
8   77874276700016  1966627 2014-02-20   973.1
9   77874276700016  1830252 2014-02-20   0.5
""")

data = pd.read_csv(raw, delim_whitespace=True)

def using_sets_drop_then_group():
    temp = data[['id', 'date', 'id2']].drop_duplicates()
    temp.groupby('id', as_index=False).agg({'date': lambda x: set(x),
                                            'id2': lambda x: len(set(x))})

def using_sets_drop_just_group():
    data.groupby('id', as_index=False).agg({'date': lambda x: set(x),
                                            'id2': lambda x: len(set(x))})

def using_unique_drop_then_group():
    temp = data[['id', 'date', 'id2']].drop_duplicates()
    temp.groupby('id', as_index=False).agg({'date': 'unique', 'id2': 'nunique'})

def using_unique_just_group():
    data.groupby('id', as_index=False).agg({'date': 'unique', 'id2': 'nunique'})

%timeit using_sets_drop_then_group()   # => 100 loops, best of 3: 4.82 ms per loop
%timeit using_sets_drop_just_group()   # => 100 loops, best of 3: 2.91 ms per loop
%timeit using_unique_drop_then_group() # => 100 loops, best of 3: 5.14 ms per loop
%timeit using_unique_just_group()      # => 100 loops, best of 3: 3.26 ms per loop
编辑:

在评论中,@ptrj建议将日期转换为
datetime64
,则
SeriesGroupBy.unique()和
SeriesGroupBy.nunique()可能会更快。唉,情况似乎并非如此,至少对于这一小部分数据来说是如此

data['parsed_date'] = pd.to_datetime(data['date'])

def using_sets_and_datetime64():
    data.groupby('id', as_index=False).agg({'parsed_date': lambda x: set(x),
                                            'id2': lambda x: len(set(x))})

def using_unique_and_datetime64():
    data.groupby('id', as_index=False).agg({'parsed_date': 'unique',
                                            'id2': 'nunique'})

%timeit using_sets_and_datetime64()    # => 100 loops, best of 3: 3.2 ms per loop
%timeit using_unique_and_datetime64()  # => 100 loops, best of 3: 3.53 ms per loop
编辑:

@MaxU建议连接100000份样本数据,这确实导致了
SeriesGroupBy.unique()
SeriesGroupBy.nunique()
优于
set

large_data = pd.concat([data] * 10**5, ignore_index=True)

def using_sets():
    large_data.groupby('id', as_index=False).agg({'date': lambda x: set(x),
                                                  'id2': lambda x: len(set(x))})

def using_unique():
    large_data.groupby('id', as_index=False).agg({'date': 'unique',
                                                  'id2': 'nunique'})

def using_sets_and_datetime64():
    large_data.groupby('id', as_index=False).agg({'parsed_date': lambda x: set(x),
                                                  'id2': lambda x: len(set(x))})

def using_unique_and_datetime64():
    large_data.groupby('id', as_index=False).agg({'parsed_date': 'unique',
                                                  'id2': 'nunique'})

%timeit using_sets()                   # => 1 loops, best of 3: 295 ms per loop
%timeit using_unique()                 # => 1 loops, best of 3: 327 ms per loop
%timeit using_sets_and_datetime64()    # => 1 loops, best of 3: 5.02 s per loop
%timeit using_unique_and_datetime64()  # => 1 loops, best of 3: 248 ms per loop

您的示例df中似乎没有
。@JonClements好吧,实际上我对它简化得太多了。一开始就修复了它-
set
将使用一个iterable,因此您可以执行
set(x)
而不是
set(x.tolist())
,这将节省一些开销。。。这对你的时间安排有什么影响?你把日期当作字符串<如果将日期转换为
datetime64
类型(且数据较大),则code>unique
可能比
set
更快。Timeit使用1M行DF:
data=pd.concat([data]*10**5,忽略索引=True)
,但不要删除重复项,因为它太小了。。。
设置(…)
解决方案应该慢得多。。。
large_data = pd.concat([data] * 10**5, ignore_index=True)

def using_sets():
    large_data.groupby('id', as_index=False).agg({'date': lambda x: set(x),
                                                  'id2': lambda x: len(set(x))})

def using_unique():
    large_data.groupby('id', as_index=False).agg({'date': 'unique',
                                                  'id2': 'nunique'})

def using_sets_and_datetime64():
    large_data.groupby('id', as_index=False).agg({'parsed_date': lambda x: set(x),
                                                  'id2': lambda x: len(set(x))})

def using_unique_and_datetime64():
    large_data.groupby('id', as_index=False).agg({'parsed_date': 'unique',
                                                  'id2': 'nunique'})

%timeit using_sets()                   # => 1 loops, best of 3: 295 ms per loop
%timeit using_unique()                 # => 1 loops, best of 3: 327 ms per loop
%timeit using_sets_and_datetime64()    # => 1 loops, best of 3: 5.02 s per loop
%timeit using_unique_and_datetime64()  # => 1 loops, best of 3: 248 ms per loop