эффективный способ вычитания 2-х фреймов данных в Python - PullRequest
1 голос
/ 22 сентября 2019

У меня есть 2 кадра данных: данные и неподходящие для следующих фигур:

 print(data.shape)

(72757056, 5)

print(ineligible.shape)

(141531, 2)

эти 2 datafrmaes имеют 2 общих столбца («штрих-код» и «магазин»). Я хочу удалить строки «данных», для которых комбинация штрих-кода и магазина не находится в «неподходящем», и я знаю, что могуполучить результат с помощью кода ниже:

data = data[~(data.loc[:,["barcode"] + (data.loc[:,"store"]).astype(str)).isin((ineligible.loc[:,"barcode"] + (ineligible.loc[:,"store"]).astype(str)))]

однако, поскольку длина «данных» очень велика, у меня закончилась память (16 ГБ) и я не смог получить результаты.Я ценю, если кто-то может предоставить мне более эффективное и меньшее использование памяти.

предположим, что примерные кадры данных выглядят следующим образом:

data = pd.DataFrame({'barcode': ['A', 'B', 'B', 'C', 'C','A', 'B', 'B', 'C', 'C'],'store': ['P5', 'P2', 'P3', 'P4', 'P5','P2','P4','P1','P1','P2'],'count1': [0,5,7,8,0,1,8,0,0,9],'count2': [0,5,7,8,0,1,8,0,0,9]})

ineligible = pd.DataFrame({'barcode': ['A', 'B', 'B', 'C', 'C'],'store': ['P1', 'P2', 'P3', 'P4', 'P5']})

, а результат должен выглядеть следующим образом: result

Ответы [ 3 ]

3 голосов
/ 22 сентября 2019

Использование здесь вещанияЭто должно быть намного быстрее, так как это векторизованный код C.

barcodes = data['barcode'].values
stores = data['store'].values

ineligible_barcodes = ineligible['barcode'].values[:, None]
ineligible_stores = ineligible['store'].values[:, None]

ineligible_codes = np.any((barcodes == ineligible_barcodes) & (stores == ineligible_stores), axis=0)
data[~ineligible_codes]

Результат:

  barcode store  count1  count2
0       A    P5       0       0
5       A    P2       1       1
6       B    P4       8       8
7       B    P1       0       0
8       C    P1       0       0
9       C    P2       9       9
1 голос
/ 22 сентября 2019

Вы можете выполнить слияние и сохранить только строки первого кадра данных:

data_merged=pd.merge(data,ineligible, on=['barcode','store'],how='left',indicator=True)
data_eligible_only=data_merged.loc[data_merged['_merge']=='left_only']
1 голос
/ 22 сентября 2019

Моя идея состоит в том, чтобы сделать вместо следующие операции:

  • Установить индекс для data в ['barcode', 'store '] .
  • Удалить строки data , где текущий индекс отсутствует в (Multi) индексе, созданном из штрих-кода и store столбцы в недопустимы .
  • Изменить штрих-код и сохранить обратно на "обычные" столбцы.

Код для этого:

data.set_index(['barcode', 'store'], inplace=True)
data.drop(data.index.difference(pd.MultiIndex.from_frame(ineligible)), inplace=True)
data.reset_index(inplace=True)

Для проверки я использовал следующие фреймы данных:

data                        ineligible

  barcode store  val          barcode store
0    1111    22   10        0    1111    22
1    1112    22   12        1    1112    22
2    1112    33   13        2    1112    44
3    1115    22   14        3    1115    22
4    1115    33   15        4    1115    44
5    1118    34   16        5    1118    34
6    1118    35   17        6    1130    33
7    1119    33   18

, получая следующий результат:

  barcode store  val
0    1111    22   10
1    1112    22   12
2    1115    22   14
3    1118    34   16

Редактироватьпосле комментария

Если вы хотите удалить строки, в которых комбинация штрих-кода и магазина равна в «неподходящем», измените «среднюю» инструкцию на:

data.drop(data.index.intersection(pd.MultiIndex.from_frame(ineligible)), inplace=True)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...