Z df poniżej,
- trzeba obliczyć medianę dla zmiennej
metric
w zespołach tm1, tm2 i tm3 na perlocid
,day
,hour
podstawa combo następnie filtruj tylko te
locid
,day
,hour
obserwacje, które mają takie samemetric
mediana między zespołamitm1
,tm2
,tm3
.set.seed(100) df <- data.frame( locid = sample(c(1111,1122,1133), 20, replace=TRUE), day = sample(c(1:3), 20, replace=TRUE), hour = sample(c(1:4), 20, replace=TRUE), team = sample(c("tm1", "tm2", "tm3"), 20, replace=TRUE), metric = sample(1:5, 20, replace=TRUE ) )
moja próba
df_medians <- df %>%
group_by(locid + day + hour + team) %>%
summarise(metric_median = median(metric))
to daje median
za team
dla każdego locid + day + hour
. Muszę się teraz dowiedzieć locid + day + hour
kombinacje, które dają taką samą medianę w zespołach tm1
, tm2
, tm3
.
df_medians %>% group_by(locid, day, hour, team) %>% summarise(??what here??)
Próbowałem z dplyr, ale rozwiązanie bazowe jest w porządku.
Jako prostszy przykład możemy spojrzeć na poniższe dane, które mają pomiary z dwóch różnych lokalizacji dla dwóch zespołów.
+-------+------+-------+-------+---------+
| locid | day | hour | team | metric |
+-------+------+-------+-------+---------+
| 1111 | 1 | 1 | tm1 | 3 |
| 1111 | 1 | 1 | tm1 | 2 |
| 1111 | 1 | 1 | tm1 | 1 |
| 1111 | 1 | 1 | tm2 | 1 |
| 1111 | 1 | 1 | tm2 | 2 |
| 1111 | 1 | 1 | tm2 | 3 |
| 1122 | 1 | 1 | tm1 | 3 |
| 1122 | 1 | 1 | tm1 | 2 |
| 1122 | 1 | 1 | tm1 | 1 |
| 1122 | 1 | 1 | tm2 | 1 |
| 1122 | 1 | 1 | tm2 | 2 |
| 1122 | 1 | 1 | tm2 | 1 |
+-------+------+-------+-------+---------+
krok 1 - oblicz medianę według grupy
+-------+------+-------+-------+-------------+
| locid | day | hour | team | metric_med |
+-------+------+-------+-------+-------------+
| 1111 | 1 | 1 | tm1 | 2 |
| 1111 | 1 | 1 | tm2 | 2 |
| 1122 | 1 | 1 | tm1 | 2 |
| 1122 | 1 | 1 | tm2 | 1 |
+-------+------+-------+-------+-------------+
Krok 2 - porównaj mediany w grupie (locid + dzień + godzina) tylko (1111, 1, 1) ma to samo metric_med we wszystkich zespołach gp1 i gp2
+-------+------+-------+-------------+
| locid | day | hour | metric_med |
+-------+------+-------+-------------+
| 1111 | 1 | 1 | 2 |
+-------+------+-------+-------------+
Odpowiedzi:
0 dla odpowiedzi № 1Jednym ze sposobów jest rozłożenie grup na jeden wiersz na każdy locid, dzień i godzinę, a następnie porównanie ich. Rozwiązanie to skaluje się dobrze dla więcej niż dwóch grup i skomplikowanych warunków.
library(dplyr)
library(tidyr)
data %>%
group_by(locid, day, hour, team) %>%
summarize(median = median(metric)) %>%
spread(team, median) %>%
filter(tm1 == tm2)
Innym możliwym rozwiązaniem jest uporządkowanie podsumowanych wyników według lokalizacji, dnia i godziny, a następnie porównanie mediany w jednym rzędzie z jej lag
. To rozwiązanie działa tylko dla dwóch grup w zespole.
data %>%
group_by(locid, day, hour, team) %>%
summarize(median = median(metric)) %>%
arrange(locid, day, hour) %>%
filter(median == lag(median))
0 dla odpowiedzi nr 2
Ponownie prześlijmy „wszystko równe”, co oznacza „zerową wariancję lub pojedynczą obserwację”.
df %>%
# per locid, day, hour, team
group_by(locid, day, hour, team) %>%
# compute median
summarize(team_median = median(metric)) %>%
# ungroup before specifying new grouping
ungroup %>%
# for locid, day, hour
group_by(locid, day, hour) %>%
# find the medians that were the same for all teams
# "the same" here is taken to mean no variance
# or having a single observation
# note that, although logical vector TRUE | NA does yield TRUE
# this is only because it must yield TRUE.
# As another example, FALSE | NA, yields NA.
# As a guard against team_medians that are NA, I add a coalesce wrapper.
# I"ve decided that missing team_medians represent non-cases, YMMV
summarize(all_equal = coalesce(n() == 1 | var(team_median) == 0), FALSE) %>%
filter(all_equal == TRUE) %>%
select(-all_equal)