2017-09-25 2 views
2

Ich habe einen Datenrahmen, die ich aus einer CSV-Datei zu lesen und sieht wie folgt aus:Datenrahmen, um verschachtelte Liste

   job name `phone number` 
      <chr> <chr>   <int> 
1  developer john   654 
2  developer mike   321 
3  developer albert   987 
4  manager dana   741 
5  manager  guy   852 
6  manager anna   936 
7  developer  dan   951 
8  developer shean   841 
9 administrative rebeca   357 
10 administrative krissy   984 
11 administrative hilma   651 
12 administrative otis   325 
13 administrative piper   654 
14  manager mendy   984 
15  manager corliss   321 

DT = structure(list(job = c("developer", "developer", "developer", 
"manager", "manager", "manager", "developer", "developer", "administrative", 
"administrative", "administrative", "administrative", "administrative", 
"manager", "manager"), name = c("john", "mike", "albert", "dana", 
"guy", "anna", "dan", "shean", "rebeca", "krissy", "hilma", "otis", 
"piper", "mendy", "corliss"), phone = c(654L, 321L, 987L, 741L, 
852L, 936L, 951L, 841L, 357L, 984L, 651L, 325L, 654L, 984L, 321L 
)), .Names = c("job", "name", "phone"), row.names = c(NA, -15L 
), class = "data.frame") 

ich es in eine Liste von Listen transformieren möchten, wo zum Beispiel:

myList$developer 

würde mir eine Liste aller Entwickler enthält, und dann

myList$developer$john 

würde mir eine Liste von Telefonnummern zugeordnet mit Entwicklern namens John. Gibt es eine einfache Möglichkeit, es zu tun?

Wenn Sie neugierig sind, warum ich so etwas tun möchte: Der eigentliche Datenrahmen, mit dem ich arbeite, ist riesig, also einen bestimmten Eintrag durch 4 Parameter zu finden (in diesem Beispiel finde ich einen spezifischer Eintrag mit 2 Parametern: Job, Name) benötigt viel zu viel Zeit mit Filter. Ich denke, dass die Hashtabellenstruktur einer verschachtelten Liste viel Zeit zum Aufbau braucht, aber in O (1) durchsuchbar wäre, was definitiv für mich funktioniert. Wenn ich falsch liege und Sie einen besseren Weg haben, würde ich es auch gerne hören.

+0

'lapply (split (df, df $ job), funktion (x) split (x $ phone_number, x $ name)) würde es tun. –

+0

@AndrewGustar das ist das gleiche wie meine Antwort ;-) – Jaap

Antwort

2

Sie können einen doppelten split mit lapply und den drop = TRUE -Parameter dafür verwenden. Wenn Sie drop = TRUE verwenden, werden Ebenen, die nicht auftreten, gelöscht, wodurch die Erstellung leerer Listenelemente verhindert wird.

Verwendung:

l <- split(dat, dat$job, drop = TRUE) 
nestedlist <- lapply(l, function(x) split(x, x[['name']], drop = TRUE)) 

Oder in einem Rutsch:

nestedlist <- lapply(split(dat, dat$job, drop = TRUE), 
        function(x) split(x, x[['name']], drop = TRUE)) 

gibt:

> nestedlist 
$administrative 
$administrative$hilma 
       job name phonenumber 
11 administrative hilma   651 

$administrative$krissy 
       job name phonenumber 
10 administrative krissy   984 

$administrative$otis 
       job name phonenumber 
12 administrative otis   325 

$administrative$piper 
       job name phonenumber 
13 administrative piper   654 

$administrative$rebeca 
      job name phonenumber 
9 administrative rebeca   357 


$developer 
$developer$albert 
     job name phonenumber 
3 developer albert   987 

$developer$dan 
     job name phonenumber 
7 developer dan   951 

$developer$john 
     job name phonenumber 
1 developer john   654 

$developer$mike 
     job name phonenumber 
2 developer mike   321 

$developer$shean 
     job name phonenumber 
8 developer shean   841 


$manager 
$manager$anna 
     job name phonenumber 
6 manager anna   936 

$manager$corliss 
     job name phonenumber 
15 manager corliss   321 

$manager$dana 
     job name phonenumber 
4 manager dana   741 

$manager$guy 
     job name phonenumber 
5 manager guy   852 

$manager$mendy 
     job name phonenumber 
14 manager mendy   984 

Gebrauchte Daten:

dat <- structure(list(job = c("developer", "developer", "developer", "manager", "manager", "manager", "developer", "developer", "administrative", "administrative", "administrative", "administrative", "administrative", "manager", "manager"), 
         name = c("john", "mike", "albert", "dana", "guy", "anna", "dan", "shean", "rebeca", "krissy", "hilma", "otis", "piper", "mendy", "corliss"), 
         phonenumber = c(654L, 321L, 987L, 741L, 852L, 936L, 951L, 841L, 357L, 984L, 651L, 325L, 654L, 984L, 321L)), 
       .Names = c("job", "name", "phonenumber"), class = "data.frame", row.names = c("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15")) 
5

die tatsächliche Datenrahmen mit ich arbeite ist riesig, so einen bestimmten Eintrag von 4 Parameter zu finden (in diesem Beispiel habe ich einen bestimmten Eintrag mit 2 Parametern finden: job, Name) braucht viel zu viel Zeit mit Filter. Ich denke, dass die Hashtabellenstruktur einer verschachtelten Liste viel Zeit zum Aufbau braucht, aber in O (1) durchsuchbar wäre, was definitiv für mich funktioniert. Wenn ich falsch liege und Sie einen besseren Weg haben, würde ich es auch gerne hören.

Offenbar Name suchen behaves like O(n), not O(1).

Ein möglicherweise besserer Weg wäre die Verwendung der Datei data.table, die die binäre Suche verwendet.

library(data.table) 
setDT(DT, key = c("job", "name")) 

get_phones = function(..., d = DT) d[list(...), phone] 

Anwendungsbeispiel

get_phones("developer", "john") 
# [1] 654 

get_phones("administrative") 
# [1] 651 984 325 654 357 

Siehe vignette("datatable-keys-fast-subset") oder die (möglicherweise veraltet) copy online.

+1

nicht als Lösung markiert, weil es keine Lösung für die Frage im Titel ist, aber es war besser für meine Bedürfnisse. Danke vielmals! – shayelk

Verwandte Themen