Как добавить разные столбцы в двух DataFrames по нескольким столбцам (Pandas) - PullRequest
0 голосов
/ 30 ноября 2018

У меня есть таблица с данными об ошибках, которые необходимо исправить.

Test df

df = pd.DataFrame({
    'store_id' : list('aaaabbbbcccc'),
    'product_id' : list('111122223333'),
    'time_create' : (1,1,1,3,1,1,2,2,10,11,12,13),
    'store_product_quantity_old' : (0,0,0,3,0,0,5,5, 0,1,2,3),
    'store_product_quantity_new' : (1,1,1,5,2,3,4,10,1,2,3,4)
})

Выбрать все дубликаты с помощью ['store_id', 'product_id', 'time_create']

dups = df[df.duplicated(subset=['store_id', 'product_id', 'time_create'], keep=False)].copy()

Рассчитать реальное значение diff

dups.loc[:, 'quantity_diff'] = dups.store_product_quantity_new - dups.store_product_quantity_old
a = dups.groupby(['store_id', 'product_id', 'time_create']).agg({'quantity_diff': 'sum'} )

Удаление дубликатов, кроме первого

x = df.drop(df[df.duplicated(subset=['store_id', 'product_id', 'time_create'])].index)

Добавление значения diff к предыдущей исключенной строке

x = x.set_index(['store_id', 'product_id',  'time_create'])
x.iloc[a.index].store_product_quantity_new  = x.iloc[a.index].store_product_quantity_old + a.quantity_diff

Но на последнем шаге это не удалось:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-129-0183d1586485> in <module>()
----> 1 x.iloc[a.index].store_product_quantity_new  = x.store_product_quantity_old + a.quantity_diff

C:\Anaconda3\lib\site-packages\pandas\core\indexing.py in __getitem__(self, key)
   1476 
   1477             maybe_callable = com._apply_if_callable(key, self.obj)
-> 1478             return self._getitem_axis(maybe_callable, axis=axis)
   1479 
   1480     def _is_scalar_access(self, key):

C:\Anaconda3\lib\site-packages\pandas\core\indexing.py in _getitem_axis(self, key, axis)
   2089         # a list of integers
   2090         elif is_list_like_indexer(key):
-> 2091             return self._get_list_axis(key, axis=axis)
   2092 
   2093         # a single integer

C:\Anaconda3\lib\site-packages\pandas\core\indexing.py in _get_list_axis(self, key, axis)
   2068             axis = self.axis or 0
   2069         try:
-> 2070             return self.obj._take(key, axis=axis)
   2071         except IndexError:
   2072             # re-raise with different error message

C:\Anaconda3\lib\site-packages\pandas\core\generic.py in _take(self, indices, axis, is_copy)
   2787         new_data = self._data.take(indices,
   2788                                    axis=self._get_block_manager_axis(axis),
-> 2789                                    verify=True)
   2790         result = self._constructor(new_data).__finalize__(self)
   2791 

C:\Anaconda3\lib\site-packages\pandas\core\internals.py in take(self, indexer, axis, verify, convert)
   4524                              dtype='int64')
   4525                    if isinstance(indexer, slice)
-> 4526                    else np.asanyarray(indexer, dtype='int64'))
   4527 
   4528         n = self.shape[axis]

C:\Anaconda3\lib\site-packages\numpy\core\numeric.py in asanyarray(a, dtype, order)
    542 
    543     """
--> 544     return array(a, dtype, copy=False, order=order, subok=True)
    545 
    546 

ValueError: setting an array element with a sequence.

Ответы [ 3 ]

0 голосов
/ 30 ноября 2018

Используйте drop_duplicates и создайте новый столбец без iloc:

dups = df[df.duplicated(subset=['store_id', 'product_id', 'time_create'], keep=False)].copy()
dups['quantity_diff'] = dups.store_product_quantity_new - dups.store_product_quantity_old
a = dups.groupby(['store_id', 'product_id', 'time_create']).agg({'quantity_diff': 'sum'})

x = df.drop_duplicates(subset=['store_id', 'product_id', 'time_create'])
x = x.set_index(['store_id', 'product_id',  'time_create'])
x['store_product_quantity_new'] =  x.store_product_quantity_old + a.quantity_diff
print (x)
                                 store_product_quantity_old  \
store_id product_id time_create                               
a        1          1                                     0   
                    3                                     3   
b        2          1                                     0   
                    2                                     5   
c        3          10                                    0   
                    11                                    1   
                    12                                    2   
                    13                                    3   

                                 store_product_quantity_new  
store_id product_id time_create                              
a        1          1                                   3.0  
                    3                                   NaN  
b        2          1                                   5.0  
                    2                                   5.0  
c        3          10                                  NaN  
                    11                                  NaN  
                    12                                  NaN  
                    13                                  NaN  

Во избежание NaN используйте add с параметром fill_value=0:

x['store_product_quantity_new'] =  (x.store_product_quantity_old
                                    .add(a.quantity_diff, fill_value=0))
print (x)
                                 store_product_quantity_old  \
store_id product_id time_create                               
a        1          1                                     0   
                    3                                     3   
b        2          1                                     0   
                    2                                     5   
c        3          10                                    0   
                    11                                    1   
                    12                                    2   
                    13                                    3   

                                 store_product_quantity_new  
store_id product_id time_create                              
a        1          1                                   3.0  
                    3                                   3.0  
b        2          1                                   5.0  
                    2                                   5.0  
c        3          10                                  0.0  
                    11                                  1.0  
                    12                                  2.0  
                    13                                  3.0  
0 голосов
/ 30 ноября 2018

О, это моя неосторожность.После того, как я закончил код, забыл iloc был использован для выбора целочисленного индекса, который не может использоваться для мультииндекс.А также, потому что loc не удалось до того, как мой код готов.Что заставляет меня думать, что мой код был неправильным.Мне действительно нужен вопрос для проверки перед публикацией. Ответ

@ jezrael меня подбадривает, но добавление x.store_product_quantity_old и a.quantity_diff к x['store_product_quantity_new'] не очень хорошая идея, я думаю.Поэтому я голосую за него без согласия.

Лучше изменить iloc на loc:

x.iloc[a.index].store_product_quantity_new  = x.iloc[a.index].store_product_quantity_old + a.quantity_diff

на

x.loc[a.index].store_product_quantity_new  = x.loc[a.index].store_product_quantity_old + a.quantity_diff

будет работать.


Снова постучитесь, и люди, которые видят этот вопрос:

iloc

Индексирование, основанное исключительно на целых местоположениях, для выбора поposition.

loc

Доступ к группе строк и столбцов по меткам или логическому массиву..loc [] в основном основан на метках, но также может использоваться с логическим массивом.

Если у вас есть какая-либо ошибка в вашем коде панд, сначала проверьте это, прежде чем отправлять вопрос.

0 голосов
/ 30 ноября 2018

использовать x.loc[a.index, 'store_product_quantity_new'] = x.store_product_quantity_old + a.quantity_diff,

Я попытался с помощью следующего кода и работал.

import pandas as pd

df = pd.DataFrame(columns = ['store_id','product_id','time_create', 'store_product_quantity_old', 'store_product_quantity_new'])
df.loc[len(df)] = ['5aab11da-5dd2-477f-916c-3ed7e81ec03f',    '460a49f8-7a8a-426d-8dec-d650d28035ee'  ,  1540305578301,   215,186]
df.loc[len(df)] = ['901b87fe-7a33-49ae-8730-de6f72167c8d' ,   '347ed0f2-423d-43b5-864a-654ebfab88e0'  ,  1540036103826,   10,  9]
df.loc[len(df)] = ['831b632e-12bd-4c23-a6fd-a18749d8d508' ,   'c0e48f01-7d37-433e-8c82-66621a83be58'  ,  1540770907795,   0 ,  20]
df.loc[len(df)] = ['31919fe6-bcef-483b-bc44-0fb2360993b2' ,   '2444245c-69d5-43ca-9138-2428acb368e0'  ,  1539659604914 ,  90,  89]
df.loc[len(df)] = ['901b87fe-7a33-49ae-8730-de6f72167c8d' ,   '4614ce9a-52a2-42c4-9fda-2f200231531e'   , 1538523837324 ,  115, 114]
df.loc[len(df)] = ['8f3dfc01-3a82-4fbf-a681-94cc807b41a1' ,   '484f911a-f0d9-43a9-bcaf-ef5e67c8f64c'   , 1539388385358 ,  5 ,  6]
df.loc[len(df)] = ['1148a913-7860-4525-b9c9-06c428baea4e' ,   '0e6ee8aa-f9f1-4541-ade7-04f3df6cbf71'    ,1538355213073 ,  171, 170]
df.loc[len(df)] = ['8d3527f7-8c25-4e47-8a8d-ddd6dcde439b' ,   'cdfaa486-75ed-4be6-8457-057d8708142a'    ,1539499795481 ,  156, 155]
df.loc[len(df)] = ['9e7ff8bf-6aa4-4731-96d3-68c875f843f6' ,   '6f157811-0b18-4144-8400-311a299e2386'    ,1538389333436 ,  37 , 36]
df.loc[len(df)] = ['8dc2853b-ffe9-4dc8-9ad6-85622eed0c74' ,   'f6b11510-f719-44d8-91a3-1b5cab1011ad'    ,1539735238709 ,  6 ,  5]
df.loc[len(df)] = ['05a2d25c-d04f-4b32-8678-7c3b31d45fbb' ,   'b7a2019a-eac1-4900-9c51-9576a77a0711'    ,1538540129711 ,  128, 127]
df.loc[len(df)] = ['05a2d25c-d04f-4b32-8678-7c3b31d45fbb' ,   'b7a2019a-eac1-4900-9c51-9576a77a0711'    ,1538540129711 ,  129, 128]
df.loc[len(df)] = ['05a2d25c-d04f-4b32-8678-7c3b31d45fbb' ,   'b7a2019a-eac1-4900-9c51-9576a77a0711'    ,1538540129711 ,  130, 129]

dups = df[df.duplicated(subset=['store_id', 'product_id', 'time_create'], keep=False)].copy()
dups['quantity_diff'] = dups['store_product_quantity_old'] - dups['store_product_quantity_new']
a = dups.groupby(['store_id', 'product_id', 'time_create']).agg({'quantity_diff': 'sum'} )
dups.loc[:, 'quantity_diff'] = dups.store_product_quantity_new - dups.store_product_quantity_old

x = df.drop(df[df.duplicated(subset=['store_id', 'product_id', 'time_create'])].index)
x = x.set_index(['store_id', 'product_id',  'time_create'])
x.loc[a.index, 'store_product_quantity_new'] = x.store_product_quantity_old + a.quantity_diff
print(x)
...