Summierung nach Levelpaaren

Wie erstelle ich Grafiken, was ist zu beachten?

Moderatoren: EDi, jogo

FR1712
Beiträge: 17
Registriert: So Nov 11, 2018 11:23 pm

Summierung nach Levelpaaren

Beitrag von FR1712 »

Guten Abend,

im Anhang habe ich ein kurzes Script, um mein Problem zu verdeutlichen. Folgende Frage: Wie kann man in einem großen Dataframe Summen nach zwei Merkmalen bilden?

Die Daten sind von der Art her wie folgt:

Code: Alles auswählen

> df
      Orte    Sorte 2016 2017 2018
1   Berlin    Äpfel    7   14    7
2   Berlin Pflaumen    4   14   14
3   Berlin Pflaumen   13   12    4
4   Berlin Pflaumen    2    7    5
5   Berlin   Birnen    4   13   14
6  Hamburg   Birnen   11   11    6
7  Hamburg Pflaumen    9    1    6
8  Hamburg Pflaumen   10   13    6
9  Hamburg   Birnen    5   15    5
10 Hamburg    Äpfel    9   12    7
11 Hamburg Pflaumen   14    5    5
12 München   Birnen    8    2    8
13 München Pflaumen   10    8    1
14 München   Birnen    5   11    3
15 München    Äpfel   13    7    7
Die beiden Merkmale, um die es geht, sind vom Typ factor. Für die einzelnen Levelpaare sind im Allgemeinen mehrerere Einträge vorhanden. Diese will ich nun gern summieren, sodass ich am Ende eine Tabelle habe, in der jedes Levelpaar einmal vorkommt und dazu für jedes Jahr die Summe dieses Levelpaares angegeben ist. Im angegebenen Beispiel würden dann die Zeilen mit gleichem Levelpaar summiert, sodass aus den 15 Zeilen am Ende 9 Zeilen werden. Das ganze soll natürlich idealerweise so erfolgen, dass es dazu eine Funktion gibt, sodass man nicht jedes Levelpaar einzeln eingeben muss. Hat da jemand eine Lösung dazu?

Hier unten ist noch ein Überblick gegeben.

Vielen Dank im Voraus und beste Grüße,
Robert

Code: Alles auswählen

str(df)
'data.frame':	15 obs. of  5 variables:
 $ Orte : Factor w/ 3 levels "Berlin","Hamburg",..: 1 1 1 1 1 2 2 2 2 2 ...
 $ Sorte: Factor w/ 3 levels "Äpfel","Birnen",..: 1 3 3 3 2 2 3 3 2 1 ...
 $ 2016 : int  7 4 13 2 4 11 9 10 5 9 ...
 $ 2017 : int  14 14 12 7 13 11 1 13 15 12 ...
 $ 2018 : int  7 14 4 5 14 6 6 6 5 7 ...
Dateianhänge
Beispiel.txt
(777 Bytes) 52-mal heruntergeladen
jogo
Beiträge: 2085
Registriert: Fr Okt 07, 2016 8:25 am

Re: Summierung nach Levelpaaren

Beitrag von jogo »

Hallo Robert,

Code: Alles auswählen

aggregate(. ~ Orte + Sorte, data=df, FUN=sum)
und nochmal komlett:

Code: Alles auswählen

###Beispiel###
set.seed(42)
#vorliegende Daten
df <- data.frame(
  Orte =rep(c("Berlin", "Hamburg", "München"), times = c(5,6,4)),
  Sorte =sample(c("Äpfel","Birnen","Pflaumen"), size = 15, replace = T),
  a =sample(1:15, size = 15, replace = T),
  b =sample(1:15, size = 15, replace = T),
  c =sample(1:15, size = 15, replace = T))
colnames(df) <- c("Orte","Sorte", 2016,2017,2018)
df
aggregate(. ~ Orte + Sorte, data=df, FUN=sum)
Gruß, Jörg
FR1712
Beiträge: 17
Registriert: So Nov 11, 2018 11:23 pm

Re: Summierung nach Levelpaaren

Beitrag von FR1712 »

Lieber Jörg,
vielen herzlichen Dank erstmal für deine Antwort. Im Beispiel klappt das auch genau so wie erwünscht. Leider klappt es bei meinen echten Daten nicht auf diese Weise. R führt den Befehl aus und erzeugt ein neuen Dataframe. Aber dort wurde eben nicht das umgesetzt, was ich erhofft hatte.
Ich scheue mich etwas davor, meine echten Daten einfach mal hochzuladen, deshalb versuche ich das erstmal zu beschreiben:
Der erste factor hat 10 level, der zweite 33 level. Der durch aggregate erzeugte Dataframe hat 17 level. Rein theoretisch wäre das zwar möglich, aber ich habe reingeschaut und das ist definitiv falsch.

Hier aber mal zum Überblick

Code: Alles auswählen

str(AD)
'data.frame':	52388 obs. of  44 variables:
 $ Metaregion: Factor w/ 10 levels "Bjørneborg-Kristinestad",..
 $ Kategorie : Factor w/ 33 levels "Alkohol_Getränke",..
 $ X1815     : num  NA NA NA NA NA NA NA NA NA NA ...
 $ X1816     : num  NA NA NA NA NA NA NA NA NA NA ...
Mein code sieht jetzt so aus:

Code: Alles auswählen

attach(AD)
AD2 <- aggregate(.~ Metaregion + Kategorie, data = AD, FUN = sum, na.rm = TRUE)
Woran könnte das liegen? Also auf jeden Fall werde ich nochmal ganz genau die Daten überprüfen, ob da alles stimmt. Aber vielleicht weißt du ja Rat?

Beste Grüße,
Robert
Benutzeravatar
EDi
Beiträge: 1599
Registriert: Sa Okt 08, 2016 3:39 pm

Re: Summierung nach Levelpaaren

Beitrag von EDi »

Rein theoretisch wäre das zwar möglich, aber ich habe reingeschaut und das ist definitiv falsch.
Woran erkennst du das? Wenn du keine reproduzierbares Beispiel zeigen möchtest, ist es sehr schwer für uns das nachzuvollziehen...
Bitte immer ein reproduzierbares Minimalbeispiel angeben. Meinungen gehören mir und geben nicht die meines Brötchengebers wieder.

Dieser Beitrag ist lizensiert unter einer CC BY 4.0 Lizenz
Bild.
FR1712
Beiträge: 17
Registriert: So Nov 11, 2018 11:23 pm

Re: Summierung nach Levelpaaren

Beitrag von FR1712 »

Erkennen kann ich das daran, dass in dem neuen Dataframe viele Levelpaare nicht auftauchen, die eigentlich vorhanden sein müssten. Also es wäre ja logisch, dass das verschwindet, was Null wird, aber es fehlen Sachen, deren Summe nicht null ergibt.

Ich wollte jetzt gerade doch einfach mal meine Daten anhängen, aber die Datei ist zu groß. Im Wesentlichen sind die von der Struktur her schon wie ich das im obigen Beispiel dargestellt habe, einziger Unterschied, der mir auffällt besteht darin, dass da sehr sehr viele NAs drin sind. Aber das dürfte da doch eigentlich keine Probleme bereiten, oder?

Mein Code sieht dann ja im Wesentlichen so aus:

Code: Alles auswählen

Arbeitsdaten <- read.csv("Arbeitsdaten.csv")
attach(Arbeitsdaten)
AD2 <- aggregate(.~ Metaregion + Kategorie, data = Arbeitsdaten, FUN = sum, na.rm = T)
Athomas
Beiträge: 768
Registriert: Mo Feb 26, 2018 8:19 pm

Re: Summierung nach Levelpaaren

Beitrag von Athomas »

Ich wollte jetzt gerade doch einfach mal meine Daten anhängen, aber die Datei ist zu groß.
Dann sende doch einen Teil, der noch passt!?

Code: Alles auswählen

attach(Arbeitsdaten)
Ohoh - wer hat Dir das böse Wort verraten?
Aber ich möchte dazu unserem attach-Beauftragten jogo nicht vorgreifen ;) !
jogo
Beiträge: 2085
Registriert: Fr Okt 07, 2016 8:25 am

Re: Summierung nach Levelpaaren

Beitrag von jogo »

Athomas hat geschrieben: Mi Nov 28, 2018 8:41 am
Ich wollte jetzt gerade doch einfach mal meine Daten anhängen, aber die Datei ist zu groß.
Dann sende doch einen Teil, der noch passt!?

Code: Alles auswählen

attach(Arbeitsdaten)
Ohoh - wer hat Dir das böse Wort verraten?
Aber ich möchte dazu unserem attach-Beauftragten jogo nicht vorgreifen ;) !
Glücklicherweise muss ich mich nicht mehr selbst echauffieren, sondern kann ganz lässig verweisen auf:

Code: Alles auswählen

library("fortunes")
fortune(379)
Wenn Du Dir etwas Gutes tun möchtes, vergiss ganz schnell diese Funktion. Der Aufruf der Funktion ist in Deinem Fall so überflüssig wie ein Kropf:

Code: Alles auswählen

Arbeitsdaten <- read.csv("Arbeitsdaten.csv")
### attach(Arbeitsdaten) ### weg damit!
AD2 <- aggregate(.~ Metaregion + Kategorie, data = Arbeitsdaten, FUN = sum, na.rm = T)
Das, was Du meinst, wofür attach() gut sein könnte, erledigt in Deinem Fall der Parameter data = Arbeitsdaten .
Dass Du den Aufruf trotzdem in Deinem Skript stehen hast, ist nur der letzte Beweis dafür, dass Dir nicht klar ist, mit was für einem Teufelszeug Du es zu tun hast.

Gruß, Jörg
Athomas
Beiträge: 768
Registriert: Mo Feb 26, 2018 8:19 pm

Re: Summierung nach Levelpaaren

Beitrag von Athomas »

Bei "großen Datenmengen" fällt mir immer data.table ein.
Ich gehe davon aus, dass Du alle Variablen, die keine Gruppeneinteilungen darstellen, summieren willst!?

Code: Alles auswählen

library(data.table)
DT <- data.table(Kategorie1=sample(LETTERS[1:10], 50000, replace=TRUE), 
                 Kategorie2=sample(letters[1:10], 50000, replace=TRUE), 
                 matrix(sample(c(NA,1:10), 50000*50, replace=TRUE, prob=c(0.5, rep(0.05,10))), ncol=50))

Ergebnis <- DT[  , lapply(.SD, sum, na.rm=TRUE), by=.(Kategorie1, Kategorie2)]
jogo
Beiträge: 2085
Registriert: Fr Okt 07, 2016 8:25 am

Re: Summierung nach Levelpaaren

Beitrag von jogo »

Hallo Robert,

die Behandlung von NAs und fehlenden levels ist in aggregate() oft nicht so, wie man es sich vorstellt. Es gibt dafür weitere Parameter in der Funktion, die man entsprechend setzen muss. ... oder man nimmt gleich ein anderes Werkzeug, bei dem die Regelungen etwas klarer sind, z.B. data.table
Das sieht dann z.B. so aus:

Code: Alles auswählen

library("data.table")
###Beispiel###
set.seed(42)
#vorliegende Daten
dt <- data.table(
  Orte =rep(c("Berlin", "Hamburg", "München"), times = c(5,6,4)),
  Sorte =sample(c("Äpfel","Birnen","Pflaumen"), size = 15, replace = T),
  '2016' =sample(1:15, size = 15, replace = T),
  '2017' =sample(1:15, size = 15, replace = T),
  '2018' =sample(1:15, size = 15, replace = T))
dt
dt[, as.list(colSums(.SD)), by=.(Orte, Sorte)]
Wenn Du aus irgend einem Grund nicht Deine vorhandenen Daten hier einbringen kannst, kannst Du auf alle Fälle Pseudodaten für uns generieren.

Gruß, Jörg
FR1712 hat geschrieben: Di Nov 27, 2018 11:38 pm Im Beispiel klappt das auch genau so wie erwünscht. Leider klappt es bei meinen echten Daten nicht auf diese Weise. R führt den Befehl aus und erzeugt ein neuen Dataframe. Aber dort wurde eben nicht das umgesetzt, was ich erhofft hatte.
Ich scheue mich etwas davor, meine echten Daten einfach mal hochzuladen, deshalb versuche ich das erstmal zu beschreiben:
Der erste factor hat 10 level, der zweite 33 level. Der durch aggregate erzeugte Dataframe hat 17 level. Rein theoretisch wäre das zwar möglich, aber ich habe reingeschaut und das ist definitiv falsch.

Woran könnte das liegen? Also auf jeden Fall werde ich nochmal ganz genau die Daten überprüfen, ob da alles stimmt. Aber vielleicht weißt du ja Rat?
FR1712
Beiträge: 17
Registriert: So Nov 11, 2018 11:23 pm

Re: Summierung nach Levelpaaren

Beitrag von FR1712 »

Athomas hat geschrieben: Mi Nov 28, 2018 8:41 am Ohoh - wer hat Dir das böse Wort verraten?
Das haben wir in der Lehrveranstaltung so gelernt :roll:
jogo hat geschrieben: Mi Nov 28, 2018 9:04 am Wenn Du Dir etwas Gutes tun möchtes, vergiss ganz schnell diese Funktion.
Das werde ich beherzigen.
jogo hat geschrieben: Mi Nov 28, 2018 9:04 am Dass Du den Aufruf trotzdem in Deinem Skript stehen hast, ist nur der letzte Beweis dafür, dass Dir nicht klar ist, mit was für einem Teufelszeug Du es zu tun hast.
Ich bin weit entfernt davon, das zu leugnen :lol:

Im Gegenteil, ich arbeite das erste mal richtig mit R. Das macht mir auch großen Spaß, aber ich stoße auf zahlreiche Fragen. Für die meisten Sachen habe ich bisher zwar Lösungen gefunden, aber bei manchen Problemen versagen dann meine Recherchekünste oder eigenen Code-Versuche. Mir fehlen da sicherlich auch die informatischen Kenntnisse.
Wenn die Qualität meiner Fragen deshalb zu wünschen übrig lässt, bitte ich da um Milde. Wie gesagt stelle ich die nur, nachdem ich auch ne Weile vorher selbst probiert habe. Ich versuche das Problem so präzise wie möglich zu beschreiben und nach Möglichkeit Code oder Daten oder so mit anzuhängen. Das mit den Pseudodaten hatte ich ja oben versucht, das hat ja scheinbar nicht so geklappt. Da muss ich wohl noch viel üben, aber ich habe ja bei Athomas jetzt gesehen, wie es geht.

Auf den ersten Blick scheint mir mit dem data.table Ansatz mein Problem gelöst. Das muss ich mir jetzt mal in Ruhe anschauen. Vielen Dank Euch auf jeden Fall erstmal!

Beste Grüße,
Robert :)
Antworten