Auf meiner Festplatte befindet sich diese 8-GB-CSV-Datei. Es hat eine "Übereinstimmung" pro Zeile.

Eine "Übereinstimmung" besteht aus einigen Daten wie id, date und winner. Aber es hat auch 10 Spieler mit all ihren Daten. Diese werden in participants.0.stats.visionScore, participants.1.stats.visionScore, ..., participants.0.stats.assists, ..., participants.9.stats.assists, ... gespeichert. Ich denke, Sie erhalten das Muster. Es ist nur participants.{number}.stats.{variable_name}. Jeder Teilnehmer hat buchstäblich Hunderte von Statistiken; Deshalb habe ich insgesamt etwa 4.000 Spalten.

Ich habe die Daten folgendermaßen eingelesen:

> d <- fread("Matches.csv")
> head(d)
   participants.1.stats.totalDamageDealt
1:                                118504
2:                                 20934
3:                                 76639
4:                                123932
5:                                160561
6:                                237046
   participants.8.stats.totalDamageTaken participants.9.stats.totalPlayerScore
1:                                 18218                                     0
2:                                 12378                                     0
3:                                 46182                                     0
4:                                 19340                                     0
5:                                 30808                                     0
6:                                 36194                                     0
... [there are thousands of lines I omit here] ...

Natürlich möchte ich jetzt eine Darstellung der Daten, wobei eine Zeile einem Teilnehmer entspricht. Ich stelle mir ein Ergebnis wie dieses vor:

> [magic]
> head(d)
   participant             stats.totalDamageDealt
1:           1                             118504
2:           2                             190143
3:           3                              46700
4:           4                              60787
5:           5                              78108
6:           6                             124761
                  stats.totalDamageTaken                stats.totalPlayerScore
1:                                 18218                                     0
2:                                 15794                                     0
3:                                 34578                                     0
4:                                 78771                                     0
5:                                 16749                                     0
6:                                 11540                                     0
...

Bei allen verfügbaren Methoden wie meld, cast und reshape muss ich jedoch alle Spalten von Hand benennen. Selbst mit patterns für meld muss ich am Ende alle meine Hunderte von Spalten pro Teilnehmer benennen. Gibt es keinen Ausweg, um dieses Ding in R lang zu machen?

1
Matmarbon 17 Jän. 2019 im 22:30

3 Antworten

Beste Antwort

Ich habe eine Antwort gefunden, die auch mit dieser riesigen Datenmenge ziemlich effizient funktioniert. Tatsächlich denke ich, dass es für dieses Szenario einfach so effizient ist wie in R:

cn <- names(d)
pc <- cn[which(grepl("participants.", cn))]
ppcn <- substring(pc[0:(length(pc)/10)], 16)
d_long <- reshape(d, direction='long', varying=pc, timevar='participant', times=c('participants.0', 'participants.1', 'participants.2', 'participants.3', 'participants.4', 'participants.5', 'participants.6', 'participants.7', 'participants.8', 'participants.9'), v.names=ppcn)

Die Idee dahinter ist, die Argumente für die Funktion reshape mit einigen zusätzlichen Codezeilen zu versehen, damit R weiß, über welche Spalten ich wirklich spreche.

Mit dieser Lösung wird mein langes d (kein Wortspiel beabsichtigt) erstellt (1) in einem einzigen Schritt, ohne dass temporäre potenziell große Tabellen erforderlich sind, und (2) ohne Typkonvertierungen, einschließlich Spalten aller Typen.

0
Matmarbon 10 März 2019 im 10:24

Ich bin nicht 100% sicher, ob ich verstehe, wie die Daten angeordnet sind, aber ich glaube, ich habe sie. Aus den Beispieldaten geht hervor, dass Teilnehmer 1 mehrere Datenzeilen für totalDamageDealt aus den Rohdaten hat und dass das Ergebnis keine Aggregation erfordert. Wenn dies nicht der Fall ist, sind möglicherweise verschiedene Schritte erforderlich. Ich musste meine eigenen Beispieldaten erstellen, um dies ausführen zu können. Wenn Sie einen minimalen Datensatz veröffentlichen möchten, der alle Möglichkeiten abdeckt, ist dies hilfreich.

Andernfalls finden Sie hier einige Methoden, um die Daten vollständig zu verlängern, um Teilnehmerinformationen zu extrahieren, und dann erneut, um sie in das gewünschte Format zu bringen. Wenn Sie eine Aggregation benötigen, um die Daten breit zu machen, geschieht dies wahrscheinlich im Schritt dcast.

library(data.table)
library(stringr)

# Create example data
dt <- data.table(participant.1.stats.visionScore = c(1,1.1,1.2,1.3,1.4,1.5),
           participant.1.stats.totalDamageDealt = c(7.1,8.1,9.1,10.1,11.1,12.1),
           participant.2.stats.visionScore = c(2,2.1,2.2,2.3,2.4,2.5),
           participant.2.stats.totalDamageDealt = c(7.2,8.2,9.2,10.2,11.2,12.2))

# Make data totally long (not wide at all)
dt <- melt(dt,measure.vars = names(dt))

# Separate participant and stat details into columns
dt[,participant := variable %>% str_extract("(?<=^participant\\.)\\d+")]
dt[,stat := variable %>% str_extract("(?<=.stats.).+")]

# Remove variable for cleanup
dt[,variable := NULL]

# Create an index to create a unique key in order to be able to dcast without aggregating
dt[,index := 1:.N, by = list(participant,stat)]

# dcast to make the data wide again
dt <- dcast(dt,index + participant ~ stat, value.var = "value")

# Sort to make it easier for a human to view the table
dt <- dt[order(participant)]

#     index participant totalDamageDealt visionScore
# 1:      1           1              7.1         1.0
# 2:      2           1              8.1         1.1
# 3:      3           1              9.1         1.2
# 4:      4           1             10.1         1.3
# 5:      5           1             11.1         1.4
# 6:      6           1             12.1         1.5
# 7:      1           2              7.2         2.0
# 8:      2           2              8.2         2.1
# 9:      3           2              9.2         2.2
# 10:     4           2             10.2         2.3
# 11:     5           2             11.2         2.4
# 12:     6           2             12.2         2.5
0
Adam Sampson 17 Jän. 2019 im 20:50

Okay, verwenden Sie Ihr bereitgestelltes Datenbeispiel:

library(data.table)

setDT(d) 

d <- melt(d, measure = patterns("^participants"), value.name = "value")

d <- d[,  `:=` (ID = gsub(".*?\\.(\\d+)\\..*","\\1", variable),
                stats = gsub(".*?(stats\\..*)$","\\1", variable))
  ][, .(variable, value, ID, stats)]
d <- dcast(d, ID ~ stats, value.var= "value", fun.aggregate = sum)

Bearbeiten: hat dies als data.table einzige Lösung für Geschwindigkeit neu geschrieben

Beachten Sie, dass Ihre Quelldaten einige zusätzliche Spalten wie participantIdentities.6.player.accountId enthalten, die Sie nicht ansprechen. Daher habe ich sie einfach ausgeschlossen. Wenn sie enthalten sein müssen, fügen Sie sie entweder zu patterns oder id.vars in melt hinzu.

Ein Hinweis: Alle Werte, die Sie umwandeln, müssen numerisch sein, sonst schlägt dcast fehl. Ich glaube, dass dies ein Problem mit Ihrem vollständigen Datensatz sein wird. Dies bedeutet, dass Sie Spalten wie participants.1.highestAchievedSeasonTier entweder als id.vars in melt richtig identifizieren oder auf andere Weise von dcast ausschließen müssen.

Ergebnis (Ich füge nur die ersten 4 Spalten von vielen ein)

  ID participants.4.timeline.xpPerMinDeltas.20-30 stats.goldEarned stats.perk3Var1
1  1                                            0                0               0
2  4                                           NA                0            3475
3  7                                            0                0               0
4  8                                            0                0               0
5  9                                            0           105872               0
0
Mako212 17 Jän. 2019 im 22:07