Funktion ähnlich wie group_by, wenn sich Gruppen nicht gegenseitig ausschließen
Ich möchte eine Funktion in R erstellen, ähnlich wiedplyr
'sgroup_by
-Funktion, die in Kombination mitsummarise
kann zusammenfassende Statistiken für einen Datensatz geben, bei demie Mitgliedschaft in @group schließt sich nicht gegenseitig aus. Das heißt, Beobachtungen können mehreren Gruppen angehören. Eine Möglichkeit, darüber nachzudenken, könnte darin bestehen, Tags in Betracht zu ziehen. Beobachtungen können zu einem oder mehreren Tags gehören, die sich überlappen können.
Zum Beispiel nimm R'sesoph
dataset https: //stat.ethz.ch/R-manual/R-devel/library/datasets/html/esoph.htm) Dokumentation einer Fall-Kontroll-Studie von Speiseröhrenkrebs. Angenommen, ich interessiere mich für die Anzahl und den Anteil der Krebsfälle insgesamt und pro "Tag", wobei die Tags: 65+ Jahre alt sind; 80+ g / Tag Alkohol; Mehr als 20 g / Tag Tabak; und eine "Hochrisikogruppe", in der die vorherigen 3 Kriterien erfüllt sind. Lassen Sie uns das Dataset in ein Langformat umwandeln (ein Teilnehmer pro Zeile) und dann diese Tags (logische Spalten) zum Dataset hinzufügen:
library('dplyr')
data(esoph)
esophlong = bind_rows(esoph %>% .[rep(seq_len(nrow(.)), .$ncases), 1:3] %>% mutate(case=1),
esoph %>% .[rep(seq_len(nrow(.)), .$ncontrols), 1:3] %>% mutate(case=0)
) %>%
mutate(highage=(agegp %in% c('65-74','75+')),
highalc=(alcgp %in% c('80-119','120+')),
hightob=(tobgp %in% c('20-29','30+')),
highrisk=(highage & highalc & hightob)
)
Mein üblicher Ansatz besteht darin, einen Datensatz zu erstellen, in dem jede Beobachtung für jedes Tag, zu dem sie gehört, dupliziert wird, und dannsummarise
dieser Datensatz:
esophdup = bind_rows(esophlong %>% filter(highage) %>% mutate(tag='age>=65'),
esophlong %>% filter(highalc) %>% mutate(tag='alc>=80'),
esophlong %>% filter(hightob) %>% mutate(tag='tob>=20'),
esophlong %>% filter(highrisk) %>% mutate(tag='high risk'),
esophlong %>% filter() %>% mutate(tag='all')
) %>%
mutate(tag=factor(tag, levels = unique(.$tag)))
summary = esophdup %>%
group_by(tag) %>%
summarise(n=n(), ncases=sum(case), case.rate=mean(case))
Dieser Ansatz ist für große Datenmengen oder für eine große Anzahl von Tags ineffizient, und mir wird häufig der Speicherplatz ausgehen, um ihn zu speichern.
Eine Alternative ist zusummarise
jedes Tag separat und binden Sie diese zusammenfassenden Datensätze anschließend wie folgt:
summary.age = esophlong %>%
filter(highage) %>%
summarise(n=n(), ncases=sum(case), case.rate=mean(case)) %>%
mutate(tag='age>=65')
summary.alc = esophlong %>%
filter(highalc) %>%
summarise(n=n(), ncases=sum(case), case.rate=mean(case)) %>%
mutate(tag='alc>=80')
summary.tob = esophlong %>%
filter(hightob) %>%
summarise(n=n(), ncases=sum(case), case.rate=mean(case)) %>%
mutate(tag='tob>=20')
summary.highrisk = esophlong %>%
filter(highrisk) %>%
summarise(n=n(), ncases=sum(case), case.rate=mean(case)) %>%
mutate(tag='high risk')
summary.all = esophlong %>%
summarise(n=n(), ncases=sum(case), case.rate=mean(case)) %>%
mutate(tag='all')
summary=bind_rows(summary.age,summary.alc,summary.tob,summary.highrisk,summary.all)
Dieser Ansatz ist zeitaufwendig und mühsam, wenn ich eine große Anzahl von Tags habe oder die Tags häufig für verschiedene Zusammenfassungsmaßnahmen in einem Projekt wiederverwenden möchte.
Die Funktion, an die ich denke, sagen Siegroup_by_tags(data, key, ...)
, das ein Argument zur Angabe des Namens der Gruppierungsspalte enthält, sollte ungefähr so funktionieren:
summary = esophlong %>%
group_by_tags(key='tags',
'age>=65'=highage,
'alc>=80'=highalc,
'tob>=20'=hightob,
'high risk'=highrisk,
'all ages'=1
) %>%
summarise(n=n(), ncases=sum(case), case.rate=mean(case))
mit dem zusammenfassenden Datensatz, der wie folgt aussieht:
> summary
tags n ncases case.rate
1 age>=65 273 68 0.2490842
2 alc>=80 301 96 0.3189369
3 tob>=20 278 64 0.2302158
4 high risk 11 5 0.4545455
5 all 1175 200 0.1702128
Sogar besser, es könnten Variablen vom Typ "Faktor" sowie "logisch" verwendet werden, so dass beispielsweise jede Altersgruppe, die über 65-Jährigen und alle Personen einzeln zusammengefasst werden können:
summaryage = esophlong %>%
group_by_tags(key='Age.group',
agegp,
'65+'=(agegp %in% c('65-74','75+')),
'all'=1
) %>%
summarise(n=n(), ncases=sum(case), case.rate=mean(case))
>summaryage
Age.group n ncases case.rate
1 25-34 117 1 0.0085470
2 35-44 208 9 0.0432692
3 45-54 259 46 0.1776062
4 55-64 318 76 0.2389937
5 65-74 216 55 0.2546296
6 75+ 57 13 0.2280702
7 65+ 273 68 0.2490842
8 all 1175 200 0.1702128
Vielleicht ist das mit @ nicht mögli...
und stattdessen müssen Sie möglicherweise einen Vektor / eine Liste von Spaltennamen für die Tags übergeben.
Irgendwelche Ideen
EDIT: Um klar zu sein, sollte die Lösung Tag- / Gruppendefinitionen und die erforderlichen Zusammenfassungsstatistiken als Argumente verwenden, anstatt in die Funktion selbst integriert zu sein. Entweder als zweistufigesdata %>% group_by_tags(tags) %>% summarise_tags(stats)
oder ein einstufigesdata %>% summary_tags(tags,stats)
Prozess