从事务数据到集合列表的有效方式

Qui*_*2k1 4 python performance list set pandas

我有一个csv文件,其中包含以下形式的交易数据

import pandas as pd
df = pd.DataFrame({'OrderID':[1,1,1,1,2,2], 'ItemID':[1,2,3,4,1,2]})
print(df)
   ItemID  OrderID
0       1        1
1       2        1
2       3        1
3       4        1
4       1        2
5       2        2
Run Code Online (Sandbox Code Playgroud)

我想获得一个列表,其中包含每个OrderID的项目集.

这可以通过以下方式获得

df.groupby('OrderID').apply(lambda x: set(x['ItemID'])).tolist()
[{1, 2, 3, 4}, {1, 2}]
Run Code Online (Sandbox Code Playgroud)

但是,在具有900万行的csv文件上,这需要一些时间.因此,我想知道是否有更快的方法?我对使用pandas或直接在.csv文件上运行的任何解决方案感兴趣


首先,我要感谢你们,感谢您的精彩投入!我从我的真实数据中抽取了50000个OrderIds(以及相应的项目)的样本,并将几个方法应用于数据集.以下是结果

BenchmarkResults

请注意,我使用了pir程序的更新版本.因此,即使我们只考虑集合输出的列表,胜利者也是divakar.

在我的整个数据集中,他的快速设置方法持续时间为5.05秒,而他的基于列表的快速方法的持续时间仅为2.32秒.从最初的115秒开始,这是一个巨大的收获!再次感谢!

piR*_*red 5

新方法
defaultdict

from collections import defaultdict

def pir(df):
    d = defaultdict(set)
    for n, g in df.groupby('OrderID').ItemID:
        d[n].update(g.values.tolist())

    return list(d.values())
Run Code Online (Sandbox Code Playgroud)

样品

df = pd.DataFrame(dict(OrderID=np.random.randint(0, 1000, 10000000),
                       ItemID=np.random.randint(0, 1000, 10000000)))
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


旧方法

uo, io = np.unique(df.OrderID.values, return_inverse=True)
ui, ii = np.unique(df.ItemID.values, return_inverse=True)

def gu(i):
    return set(ui[ii[io == i]].tolist())

[gu(i) for i in range(len(uo))]

[{1, 2, 3, 4}, {1, 2}]
Run Code Online (Sandbox Code Playgroud)

旧的时间
码:

def pir(df):
    uo, io = np.unique(df.OrderID.values, return_inverse=True)
    ui, ii = np.unique(df.ItemID.values, return_inverse=True)

    def gu(i):
        return set(ui[ii[io == i]].tolist())

    return [gu(i) for i in range(len(uo))]

def jez(df):
    arr = df.groupby('OrderID')['ItemID'].unique().values
    return [set(v) for v in arr]

def div(df):
    a = df.values
    sidx = a[:,1].argsort(kind='mergesort')
    cut_idx = np.nonzero(a[sidx[1:],1] > a[sidx[:-1],1])[0]+1
    out = np.split(a[sidx,0], cut_idx)
    return list(map(set,out))

def quik(df):
    return df.groupby('OrderID').apply(lambda x: set(x['ItemID'])).tolist()
Run Code Online (Sandbox Code Playgroud)

有样本数据
在此输入图像描述

有更多数据

df = pd.DataFrame(dict(OrderID=np.random.randint(0, 10, 10000),
                       ItemID=np.random.randint(0, 10, 10000)))
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

更多数据

df = pd.DataFrame(dict(OrderID=np.random.randint(0, 10, 10000000),
                       ItemID=np.random.randint(0, 10, 10000000)))
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述