Python: Как мне объединить строки с одинаковым именем «Ocode» или «Ccode в dataframe

#python #excel #pandas #dataframe

#python #excel #pandas #dataframe

Вопрос:

Я подумываю об использовании pandas для объединения нескольких повторяющихся строк «Ocode» и «Ccode». В идеале мне нужен только один «Ocode» или «Ccode» на строку. При наличии повторяющихся дат в c # # (например, c21) сохраняется только последняя дата. Отдельные даты в разных столбцах с одинаковым «Ocode» /»Ccode» также должны быть объединены.

(Для справочных целей: код O и C соответственно представляет код организации и код корпорации.)

Это заголовок фрейма данных.

 Num      Ocode      Ccode         c21  c57         c58  c59  c70         c71         c74         c75
0    BK0001000        NaN         NaN  NaN         NaN  NaN  NaN         NaN         NaN  2021-02-09
1    CU0030000        NaN         NaN  NaN         NaN  NaN  NaN  2021-12-31         NaN         NaN
2    CU0030000        NaN         NaN  NaN         NaN  NaN  NaN  2021-12-31         NaN         NaN
3    CU0048000        NaN         NaN  NaN  2018-06-19  NaN  NaN         NaN         NaN         NaN
4    CU0056000        NaN         NaN  NaN         NaN  NaN  NaN         NaN  2020-06-04         NaN
...        ...        ...         ...  ...         ...  ...  ...         ...         ...         ...         

2384       NaN  CU0280002  2017-12-31  NaN         NaN  NaN  NaN         NaN         NaN         NaN
2385       NaN  CU0280002  2016-12-31  NaN         NaN  NaN  NaN         NaN         NaN         NaN
2386       NaN  CU0280002         NaN  NaN         NaN  NaN  NaN         NaN  2017-12-31         NaN
2387       NaN  CU0659001         NaN  NaN         NaN  NaN  NaN         NaN  2022-05-31         NaN
 

Который должен стать —->

 Num      Ocode      Ccode         c21  c57         c58  c59  c70         c71         c74         c75
0    BK0001000        NaN         NaN  NaN         NaN  NaN  NaN         NaN         NaN  2021-02-09
1    CU0030000        NaN         NaN  NaN         NaN  NaN  NaN  2021-12-31         NaN         NaN
3    CU0048000        NaN         NaN  NaN  2018-06-19  NaN  NaN         NaN         NaN         NaN
4    CU0056000        NaN         NaN  NaN         NaN  NaN  NaN         NaN  2020-06-04         NaN
...        ...        ...         ...  ...         ...  ...  ...         ...         ...         ...         
2384       NaN  CU0280002  2017-12-31  NaN         NaN  NaN  NaN         NaN  2017-12-31         NaN
2387       NaN  CU0659001         NaN  NaN         NaN  NaN  NaN         NaN  2022-05-31         NaN
 

Попытка:

 import os
import xlsxwriter
import pandas as pd
import numpy as np

# Pandas and XR

df = pd.read_excel('Result - Company.xlsx')

#ic = 'c21'#IndustryCode
ic = 'c57'
#ic = 'c58'
#ic = 'c59'
#ic = 'c70'
#ic = 'c71'
#ic = 'c74'
#ic = 'c75'

df[ic] = pd.to_datetime(df[ic]) # , errors='coerce'
df = df.sort_values(ic).drop_duplicates('Ccode', keep='last')
 

и выполните слияние один за другим. Однако этот метод имеет тенденцию удалять информацию в другом столбце при работе с одним из столбцов c # # (т.Е. c21)

df.to_excel(ic ‘.xlsx’, index=False)

Комментарии:

1. Если Ocode существует, то Ccode всегда NaN? Если Ccode существует, то Ocode всегда NaN?

2. Бывают случаи, когда оба существуют, но в этом случае Ccode можно удалить и сохранить Ocode только для простоты.

3. Ответ был отредактирован EDIT

Ответ №1:

Одна из идей заключается в группировании по обоим столбцам с заменой NaN , чтобы избежать удаления этих групп в более старых версиях pandas с GroupBy.last помощью для последних не пропущенных значений для групп:

 df = (df.assign(Ocode = df['Ocode'].fillna('nan'),Ccode = df['Ccode'].fillna('nan'))
        .groupby(['Ocode','Ccode'])
        .last()
        .reset_index()
        .replace({'Ocode': {'nan':np.nan}, 'Ccode':{'nan':np.nan}}))
 

Для последних версий pandas:

 df = (df.groupby(['Ocode','Ccode'])
        .last()
        .reset_index())
 

 print (df)
       Ocode      Ccode         c21  c57         c58  c59  c70         c71  
0  BK0001000        NaN         NaN  NaN         NaN  NaN  NaN         NaN   
1  CU0030000        NaN         NaN  NaN         NaN  NaN  NaN  2021-12-31   
2  CU0048000        NaN         NaN  NaN  2018-06-19  NaN  NaN         NaN   
3  CU0056000        NaN         NaN  NaN         NaN  NaN  NaN         NaN   
4        NaN  CU0280002  2016-12-31  NaN         NaN  NaN  NaN         NaN   
5        NaN  CU0659001         NaN  NaN         NaN  NaN  NaN         NaN   

          c74         c75  
0         NaN  2021-02-09  
1         NaN         NaN  
2         NaN         NaN  
3  2020-06-04         NaN  
4  2017-12-31         NaN  
5  2022-05-31         NaN  
 

Редактировать:

Решение выше протестируйте комбинацию обоих столбцов, если необходимо установить приоритет Ocode , это означает, что установлено NaN Ccode значение, если существуют оба варианта использования перед решением выше:

 df.loc[df['Ocode'].notna() amp; df['Ocode'].notna(), 'Ccode'] = np.nan
 

РЕДАКТИРОВАНИЕ 1: одна идея, обрабатывающая оба кода отдельно:

 df1 = (df.assign(Ocode = df['Ocode'].fillna('nan'))
         .drop('Ccode', axis=1)
         .groupby('Ocode')
         .last()
         .reset_index())

df2 = (df.assign(Ccode = df['Ccode'].fillna('nan'))
         .drop('Ocode', axis=1)
         .groupby('Ccode')
         .last()
         .reset_index())

both = (pd.concat([df1, df2], sort=False)
          .replace({'Ocode': {'nan':np.nan}, 'Ccode':{'nan':np.nan}}))
 

Комментарии:

1. Я столкнулся с проблемой, когда он сохранял только строки, в которых были как Ocode, так и Ccode, и удалил все остальное.

2. Мне удалось решить проблему, выполнив это дважды для Ocode и Ccode отдельно. Спасибо!