Объединить строки с одинаковой датой, чтобы заполнить пробелы / наны, используя pandas - PullRequest
0 голосов
/ 09 января 2020

У меня есть большой набор данных (100К строк) химических параметров и даты, когда они были измерены для многочисленных местоположений (идентификаторов). Некоторые из этих записей были разбиты на строки с одинаковой датой. Я хотел бы рекомбинировать их.

import pandas as pd
import numpy as np

df1=pd.DataFrame(np.array([["Site 1","1/12/2029",3,0.001,np.nan],["Site 1","1/12/2029",np.nan,np.nan,3],["Site 1","2/12/2029",7,np.nan,3],
                           ["Site 1","2/12/2029",np.nan,0.001,np.nan],["Site 2","1/12/2029",3,0.001,3],["Site 1","3/12/2029",5,0.005,3],
                           ["Site 2","2/12/2029",np.nan,np.nan,3],["Site 2","2/12/2029",np.nan,0.001,np.nan]]),
                 columns=["ID","Date", 'Na', 'SO4','Mg'])
df1['Date'] = pd.to_datetime(df1['Date'],format= '%d/%m/%Y',dayfirst=True)
df1

Out[8]:
       ID       Date   Na    SO4   Mg
0  Site 1 2029-12-01    3  0.001  nan
1  Site 1 2029-12-01  nan    nan    3
2  Site 1 2029-12-02    7    nan    3
3  Site 1 2029-12-02  nan  0.001  nan
4  Site 2 2029-12-01    3  0.001    3
5  Site 1 2029-12-03    5  0.005    3
6  Site 2 2029-12-02  nan    nan    3
7  Site 2 2029-12-02  nan  0.001  nan

Я намеренно немного перемешал ордера, и в моих данных все еще могут быть пустые столбцы.

Результат, который я хотел бы получить:

Out[2]:
       ID       Date   Na    SO4 Mg
0  Site 1 2029-12-01    3  0.001  3
1  Site 1 2029-12-02    7  0.001  3
2  Site 2 2029-12-01    3  0.001  3
3  Site 1 2029-12-03    5  0.005  3
4  Site 2 2029-12-02  nan  0.001  3

Которые являются значениями химических параметров (Na, SO4 и Mg) для одной и той же даты и сжатого идентификатора, удаляя значения nan (значения nans останутся там, где нет записи для даты и идентификатора в любых строках с этой датой и ID.

Я попробовал это:

df_new=df1.groupby(['ID','Date']).apply(pd.DataFrame.sort_values, 'Date').fillna(method='ffill')
df_new

Out[7]:
                         ID       Date   Na    SO4   Mg
ID     Date
Site 1 2029-12-01 1  Site 1 2029-12-01  nan    nan    3
       2029-12-02 0  Site 1 2029-12-02    3  0.001  nan
                  2  Site 1 2029-12-02    7    nan    3
                  3  Site 1 2029-12-02  nan  0.001  nan
       2029-12-03 5  Site 1 2029-12-03    5  0.005    3
Site 2 2029-12-01 4  Site 2 2029-12-01    3  0.001    3
       2029-12-02 6  Site 2 2029-12-02  nan    nan    3
                  7  Site 2 2029-12-02  nan  0.001  nan

Но, похоже, это не соответствует ожиданиям, а также вводит странный индексный столбец.

Ответы [ 2 ]

2 голосов
/ 09 января 2020

Если возможно больше не пропущенных значений для комбинаций ID и Date, то решение более сложное:

#because sample data     
df1 = df1.mask(df1 == 'nan')

df1 = (df1.sort_values(['ID','Date'])
          .groupby(['ID','Date'])
          .apply(lambda x: x.ffill().bfill())
          .drop_duplicates())
print (df1)
       ID       Date   Na    SO4 Mg
0  Site 1 2029-12-01    3  0.001  3
2  Site 1 2029-12-02    7  0.001  3
5  Site 1 2029-12-03    5  0.005  3
4  Site 2 2029-12-01    3  0.001  3
6  Site 2 2029-12-02  NaN  0.001  3
1 голос
/ 09 января 2020

Если в комбинациях ID и Date всегда есть только одно не ошибочное значение, вам потребуется только GroupBy.first ( Это быстрее , чем groupby.apply). В противном случае вы должны использовать решение @ Jezrael's :

#df1 = df1.replace('nan',np.nan)
df1.groupby(['ID','Date'],as_index = False).first()

Выход

       ID       Date   Na    SO4 Mg
0  Site 1 2029-12-01    3  0.001  3
1  Site 1 2029-12-02    7  0.001  3
2  Site 1 2029-12-03    5  0.005  3
3  Site 2 2029-12-01    3  0.001  3
4  Site 2 2029-12-02  NaN  0.001  3
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...