【问题标题】:How to use numpy vectorization to find different data columns in the same column of two huge dataframes?如何使用 numpy 向量化在两个巨大数据帧的同一列中查找不同的数据列?
【发布时间】:2021-06-28 23:20:32
【问题描述】:

我有两个数据框,df1df2,它们都有相同的列 datedf1date列有几千万行,df1date列不完整,可能重复。 df2 大约有几千行。 df2date 列完整,不再重复。如何使用numpyvectorization找出df1中不存在但df2中存在的date1数据并生成numpyndarray? 我试过np.wheregroupby.size,但我找不到正确的使用方法。

【问题讨论】:

  • df2[~df2['date'].isin(df1['date'])].
  • 或者如果你只想要日期,你可以使用 Python:set(df2['date']).differrence(set(df1['date']))
  • @QuangHoang 请不要将答案发布为 cmets。
  • @orlp,Quang 在声誉方面比你更有优势 :) 我知道对此存在不同意见,但我的理念是评论它是否是一个快速、未经测试的想法。通过解释和测试,我的答案要长得多。是的,有时 OP 要求我将其作为答案,以便他检查是否关闭。还不如因为走反了而被骂:)
  • set(df2['date']).differrence(set(df1['date'])) 接受AttributeError: 'set' object has no attribute 'differrence'

标签: python pandas dataframe numpy vectorization


【解决方案1】:

您也可以在 cmets 推荐的解决方案之上使用它:

df2[~np.in1d(df2['date'],df1['date'])]['date'].to_numpy()

【讨论】:

  • 这个方法我执行了十多分钟,但结果是正确的。在执行这条语句之前,我先执行df1 = df1.drop_duplicates(['date']),速度很快。在Quang Hoang的两个回答中,df2[~df2['date'].isin(df1['date'])]可以正常执行,但是set(df2['date']).differrence(set(df1[ 'date']))带来了错误,因为Quang Hoang使用了cmets,Ehsan和Chuncheng的回答是一样的,Ehsan先回答,所以我接受了@Ehsan的回答跨度>
【解决方案2】:

如果我的理解正确,我会按照您的描述生成一个演示数据集。 我的发现是功能很简单,但是时间成本却不是。

  • 如果您可以等待,推荐的解决方案是一种选择, 因为扫描 10,000 / 100,000 大小的 df1 大约需要 0.4 / 4 秒, 并且呈线性增长, 我相信它会达到你的申请无法忍受的时间;

  • 如果您有足够大的内存,您可以使用我的“设置解决方案”,它将提供相同(正确)的结果,并且在 3,000,000 大小的 df1 上只需 0.1885 秒。

--------------- Experiment [10000] starts ------------------------------
Recommended solution [10000] costs 0.49669885635375977 seconds
Set solution [10000] costs 0.001967191696166992 seconds
[ True]
--------------- Experiment [100000] starts ------------------------------
Recommended solution [100000] costs 4.4930009841918945 seconds
Set solution [100000] costs 0.006981611251831055 seconds
[ True]
--------------- Experiment [1000000] starts ------------------------------
Set solution [1000000] costs 0.06779003143310547 seconds
--------------- Experiment [3000000] starts ------------------------------
Set solution [3000000] costs 0.18847417831420898 seconds

以下是我的代码

# %%
import time
import random
import datetime
import numpy as np
import pandas as pd

# %%
n = int(3e3)
today = datetime.date.today()
delta = datetime.timedelta(days=1)

for k in [int(1e4), int(1e5), int(1e6), int(3e6)]:
    print(
        f'--------------- Experiment [{k}] starts ------------------------------')
    days = ['{}'.format(today + i * delta) for i in range(n)]

    # Generate df2
    df2 = pd.DataFrame()
    df2['date'] = days
    df2

    # Generate df1
    df1 = pd.DataFrame()
    df1['date'] = random.choices(days[:-10], k=k)
    df1

    # Recommended solution.
    # It won't run at n of 1e6, since it will cost too much time.
    if k < 1e6:
        t0 = time.time()
        o1 = df2[~np.in1d(df2['date'], df1['date'])]['date']
        print(f'Recommended solution [{k}] costs', time.time() - t0, 'seconds')
        o1

    # Set solution
    t0 = time.time()
    set1 = set(df1['date'])
    o2 = df2['date'][df2['date'].map(lambda x: x not in set1)]
    print(f'Set solution [{k}] costs', time.time() - t0, 'seconds')
    o2

    # Compare the results of the two solutions
    if k < 1e6:
        print((o1 == o2).unique())

# %%


【讨论】:

  • 这似乎与@Quang Hoang 的答案相同,当我发布提交时我没有看到它。很抱歉。
【解决方案3】:

我找到了另一种方式,使用np.setdiff1d,代码如下:

from time import time
start = time()
n2 = np.setdiff1d(df2.date.values, df1.date.drop_duplicates().to_numpy())
print('len df1:%d  df2:%d' % (len(df1), len(df2)))
stop = time()
print(stop - start)

结果是:

len df1: 11351055  df2:7406  
1.6254549026489258

【讨论】:

    猜你喜欢
    • 2021-01-08
    • 1970-01-01
    • 2017-11-02
    • 1970-01-01
    • 2020-07-10
    • 2022-01-08
    • 1970-01-01
    • 2017-01-03
    • 1970-01-01
    相关资源
    最近更新 更多