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

Antworten auf die Frage(10)

Ihre Antwort auf die Frage