Объединение перекрывающихся наборов данных
Иногда появляется необходимость комбинировать несколько наборов данных, при котором имеющиеся значения одного набора могли бы заменять соответствующие отсутствующие значения другого набора. Например у нас есть две серии:
s1 = pd.Series([0, np.nan, 2, 3, np.nan])
s2 = pd.Series([np.nan, 1, 2, 3, np.nan])
Мы видим, что некоторые пропущенные значения в одной серии, могут быть заменены на имеющиеся значения из другой, а значит было бы круто объединить эти эначения вместе. Это можно сделать с помощью метода combine_first()
:
s1.combine_first(s2)
0 0.0 1 1.0 2 2.0 3 3.0 4 NaN dtype: float64
В итоге осталось всего одно значение NaN, которое отсутствует в обеих сериях. Однако, данный метод несколько интереснее чем может показаться. Допустим, в одной серии хранятся свежеполученные данные, но этих данных мало и некоторые из них являются пропущенными, а в другой серии, хранятся не совсем актуальные, но все же полезные данные. Мы конечно можем заменять NaN-ы на среднее или медианное значение, но иногда гораздо целесообразнее заменять их на соответствующие значения из предыдущих выборок. Итак, допустим первый набор данных выглядит так:
data_1 = pd.Series([0, 1, np.nan, 3, 4, np.nan])
А другой, вот так:
data_2 = pd.Series([1, np.nan, 3, np.nan, 9, 5, 4, 1])
Тогда объединить два набора можно так:
data_1.combine_first(data_2)
0 0.0 1 1.0 2 3.0 3 3.0 4 4.0 5 5.0 6 4.0 7 1.0 dtype: float64
Заметьте, что в первом наборе данных NaN-ы были заменены на соответствующие значения из второго набора, а так же к нему в "хвост" добавились данные из второго набора. Иногда такое добавление данных в конец является нежелательным и поэтому в результат можно включить только срез необходимой длины:
data_1.combine_first(data_2)[:len(data_1)]
0 0.0 1 1.0 2 3.0 3 3.0 4 4.0 5 5.0 dtype: float64
Данный метод, пригоден для датафреймов и выполняет комбинирование данных в соответствующих столбцах. Для примера давайте сконструируем два датафрейма:
np.random.seed(5)
data = np.random.choice([11, 11, np.nan], (3, 3))
df1 = pd.DataFrame(data,
columns=list('ABC'))
df1
A | B | C | |
---|---|---|---|
0 | NaN | 11.0 | NaN |
1 | NaN | 11.0 | 11.0 |
2 | 11.0 | 11.0 | NaN |
np.random.seed(15)
data = np.random.choice([22, 22, np.nan], (5, 3))
df2 = pd.DataFrame(data,
columns=list('ACD'))
df2
A | C | D | |
---|---|---|---|
0 | 22.0 | 22.0 | 22.0 |
1 | 22.0 | 22.0 | 22.0 |
2 | 22.0 | NaN | 22.0 |
3 | 22.0 | 22.0 | 22.0 |
4 | NaN | NaN | 22.0 |
Что бы дополнить первый датафрейм данными из второго датафрейма достаточно выполнить слудующую команду:
df1.combine_first(df2)
A | B | C | D | |
---|---|---|---|---|
0 | 22.0 | 11.0 | 22.0 | 22.0 |
1 | 22.0 | 11.0 | 11.0 | 22.0 |
2 | 11.0 | 11.0 | NaN | 22.0 |
3 | 22.0 | NaN | 22.0 | 22.0 |
4 | NaN | NaN | NaN | 22.0 |
На самом деле combine_first()
вызывает более общий метод - DataFrame.combine()
, который позволяет задавать собственные функции, определяющие, то как должно выполняться объединение данных.