数据框到嵌套列表

sha*_*elk 3 performance nested r list dataframe

我有一个数据框,我从.csv文件中读取,看起来像这样:

              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")
Run Code Online (Sandbox Code Playgroud)

我想将其转换为列表列表,例如:

myList$developer
Run Code Online (Sandbox Code Playgroud)

会给我一个包含所有开发人员的列表,然后

myList$developer$john
Run Code Online (Sandbox Code Playgroud)

会给我一个与名叫John的开发者相关联的电话号码列表.这有什么简单的方法吗?

如果你好奇我为什么要这样做:我正在使用的实际数据框是巨大的,所以通过4个参数找到一个特定的条目(在这个例子中我可以找到一个具有2个特定条目参数:job,name)使用过滤器占用太多时间.我认为嵌套列表的哈希表结构可能需要花费大量时间来构建,但是可以在O(1)中搜索,这对我来说绝对有效.如果我错了,你有更好的方法,我也很乐意听.

Jaa*_*aap 7

您可以使用双splitlapplydrop = TRUE该-parameter。使用drop = TRUE将删除不会发生的级别,从而防止创建空列表元素。

使用:

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

或者一口气:

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

给出:

> 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
Run Code Online (Sandbox Code Playgroud)

使用数据:

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"))
Run Code Online (Sandbox Code Playgroud)


Fra*_*ank 6

我正在使用的实际数据框是巨大的,因此通过4个参数查找特定条目(在此示例中,我可以找到具有2个参数的特定条目:job,name)使用过滤器需要花费太多时间.我认为嵌套列表的哈希表结构可能需要花费大量时间来构建,但是可以在O(1)中搜索,这对我来说绝对有效.如果我错了,你有更好的方法,我也很乐意听.

显然,名称查找的行为类似于O(n),而不是O(1).

一种可能更好的方法是使用data.table,它使用二进制搜索.

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

get_phones = function(..., d = DT) d[list(...), phone]
Run Code Online (Sandbox Code Playgroud)

用法示例

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

get_phones("administrative")
# [1] 651 984 325 654 357
Run Code Online (Sandbox Code Playgroud)

在线查看vignette("datatable-keys-fast-subset")或(可能过时)复制.