Прошу прощения за довольно веское объяснение, но надеюсь, что вы поймете эту идею.
Я пользователь R, и я считаю, что возможности Tidyverse в обработке данных действительно мощные. Но недавно я начал изучать Python, и в частности pandas, чтобы расширить свои возможности в анализе данных. Инстинктивно я пытаюсь сделать что-то в pandas, как я делал это, когда использовал dplyr.
Поэтому мой вопрос заключается в том, является ли какой-либо эквивалент точки dplyr при использовании цепочки методов в pandas.
В этом примере показан расчет минимального значения из всех значений, превышающих текущее значение в test_df ['data'] для каждой группы и для тех же вычислений, но для нового столбца.
Пример R:
require(dplyr)
require(purrr)
test_df = data.frame(group = rep(c(1,2,3), each = 3),
data= c(1:9))
test_df %>%
group_by(group) %>%
mutate(., min_of_max = map_dbl(data, ~data[data > .x] %>% min())) %>%
mutate(., min_of_max_2 = map_dbl(min_of_max, ~min_of_max[min_of_max > .x] %>% min()))
Вывод:
# A tibble: 9 x 4
# Groups: group [3]
group data min_of_max min_of_max_2
<dbl> <int> <dbl> <dbl>
1 1 1 2 3
2 1 2 3 Inf
3 1 3 Inf Inf
4 2 4 5 6
5 2 5 6 Inf
6 2 6 Inf Inf
7 3 7 8 9
8 3 8 9 Inf
9 3 9 Inf Inf
Я знаю этот dplyr даже не требует точки, но я поставил его для лучшего понимания специфики c моего вопроса
То же самое в Pandas
Неверный пример:
import pandas as pd
import numpy as np
test_df = (
pd.DataFrame({'A': np.array([1,2,3]*3), 'B': np.array(range(1,10))})
.sort_values(by = ['A', 'B'])
)
(test_df.assign(min_of_max = test_df.apply(lambda x: (test_df.B[(test_df.B > x.B) &
(test_df.A[test_df.A == x.A])]).min(), axis = 1))
.assign(min_of_max2 = 'assume_dot_here'.apply(lambda x: (test_df.min_of_max[(test_df.min_of_max > x.min_of_max) &
(test_df.A[test_df.A == x.A])]).min(), axis = 1)))
В этом примере поместить точку в секунду .assign
было бы отличной способностью, но она не работает в pandas.
Действительный пример, который разрушает цепочку:
test_df = test_df.assign(min_of_max = test_df.apply(lambda x:
(test_df.B[(test_df.B > x.B) & (test_df.A[test_df.A == x.A])]).min(), axis = 1))
test_df = test_df.assign(min_of_max2 = test_df.apply(lambda x :
(test_df.min_of_max[(test_df.min_of_max > x.min_of_max) & (test_df.A[test_df.A
== x.A])]).min(), axis = 1))
Вывод:
A B min_of_max min_of_max2
0 1 1 4.0 7.0
3 1 4 7.0 NaN
6 1 7 NaN NaN
1 2 2 5.0 8.0
4 2 5 8.0 NaN
7 2 8 NaN NaN
2 3 3 6.0 9.0
5 3 6 9.0 NaN
8 3 9 NaN NaN
Так есть ли какой-нибудь удобный способ вызвать объект из предыдущей части цепочки в секунду .assign
? Поскольку при использовании test_df.apply()
во втором .assign будет использоваться исходный test_df без вычислений test_df['min_of_max']
Извините за нечитаемый код в Python, я все еще выясняю, как писать более ясно.