Я довольно новичок в python и пытаюсь отфильтровать значения из фрейма данных по двум столбцам, используя значения, указанные в отдельном фрейме данных +, используя допуск, чтобы указать значения "достаточно близко", чтобы быть равными. Я хотел бы отфильтровать данные путем индексации по дате, а затем по заданным c глубинам, выбранным для строки.
Мои данные CTD
настроены так (фактические данные имеют несколько параметров, кроме Temperature (deg C)
, но для простоты):
Date Depth (m) Temperature (deg C)
0 2016-09-20 0.11 14.29
1 2016-09-20 0.15 14.29
2 2016-09-20 0.29 14.30
3 2016-09-20 0.44 14.32
4 2016-09-20 0.55 14.33
... ... ...
1546 2017-04-27 23.89 8.50
1547 2017-04-27 24.31 8.49
1548 2017-04-27 24.56 8.50
1549 2017-04-27 24.61 8.55
1550 2017-04-27 24.71 8.57
С индексным фреймом данных (value_ind
) для фильтрации данных по:
Date Depth (m)
476 2016-09-20 1.0
477 2016-09-20 2.7
478 2016-09-20 9.7
479 2016-09-20 21.0
480 2016-10-04 1.0
.. ... ...
552 2017-08-09 30.0
553 2017-09-30 0.0
554 2017-09-30 1.0
555 2017-09-30 4.0
556 2017-09-30 8.0
Я прочитал несколько постов с похожими проблемы и моя первоначальная попытка последовали за решением, предложенным здесь:
pandas - фильтровать кадр данных другим кадром данных по элементам строки
# Convert dates to integers to be recognizable by indexing
value_ind['Date'] = value_ind['Date'].values.astype('float64')
CTD['Date'] = CTD['Date'].values.astype('float64')
keys = list(CTD.columns.values)
keys = keys[0:2] # limits to date/depth to index by
ind1 = CTD.set_index(keys).index
ind2 = value_ind.set_index(keys).index
# Find CTD values corresponding to sampling dates, depths:
CTD_values = CTD[ind1.isin(ind2)]
Это дает почти те результаты, которые мне нужны; тем не менее, я понял, что pandas.DataFrame.isin()
не имеет аргумента допуска и оценивает значения только как равные (==
) друг другу, а поскольку столбцы Depth (m)
в двух моих данных имеют разную точность с плавающей точкой, некоторые значения заканчиваются до исключен.
numpy.isclose()
кажется следующим лучшим решением, но до сих пор я пытался:
CTD_values = CTD[np.isclose(ind1, ind2, atol=0.1).any(1)]
Чтобы исправить мою предыдущую попытку, но это не удалось (я думаю, из-за того, что ind
переменные являются кортежами). Я также попытался сгруппировать сначала по Date
, а затем запустить условный аргумент для фильтрации по Depth (m)
по направлениям:
CTD_values = CTD[CTD.groupby(['Date', np.isclose(CTD['Depth (m)'].values[:, None], list(value_ind['Depth (m)']),atol=0.1).any(1)])]
Но все же не повезло.
Я пытался использовать значение допуска 0,1, но в идеале я хотел бы использовать решение, которое могло бы указать допуск, определяющий минимальную разницу между двумя кадрами данных вдоль строк:
x = np.min(np.abs(ind1-ind2))
Чтобы отфильтровать случаи, когда значения Depth (m)
слишком близки для дифференциации, в результате чего 2 и более значения параметра будут найдены при одном и том же значении Depth (m)
. Я не уверен, что вместо этого лучше использовать циклы for, но любые предложения будут с благодарностью приняты!