如何将数据框转换为嵌套列表?

7
我有一个数据框,想要将其转化为具有自定义嵌套级别的嵌套列表。以下是我的做法,但我相信有更好的方法:
data <- data.frame(city=c("A", "A", "B", "B"), street=c("a", "b", "a", "b"), tenant=c("Smith","Jones","Smith","Jones"), income=c(100,200,300,400))

nested_data <- lapply(levels(data$city), function(city){
    data_city <- subset(data[data$city == city, ], select=-city)
    list(city = city, street_values=lapply(levels(data_city$street), function(street){
        data_city_street <- subset(data_city[data_city$street == street, ], select=-street)
        tenant_values <- apply(data_city_street, 1, function(income_tenant){
            income_tenant <- as.list(income_tenant)
            list(tenant=income_tenant$tenant, income=income_tenant$income)
        })
        names(tenant_values) <- NULL
        list(street=street, tenant_values=tenant_values)
    }))
})

JSON 的输出看起来像这样:
library(rjson)
write(toJSON(nested_data), "")
[{"city":"A","street_values":[{"street":"a","tenant_values":[{"tenant":"Smith","income":"100"}]},{"street":"b","tenant_values":[{"tenant":"Jones","income":"200"}]}]},{"city":"B","street_values":[{"street":"a","tenant_values":[{"tenant":"Smith","income":"300"}]},{"street":"b","tenant_values":[{"tenant":"Jones","income":"400"}]}]}]

# or prettified:

[
  {
    "city": "A",
    "street_values": [
      {
        "street": "a",
        "tenant_values": [
          {
            "tenant": "Smith",
            "income": "100"
          }
        ]
      },
      {
        "street": "b",
        "tenant_values": [
          {
            "tenant": "Jones",
            "income": "200"
          }
        ]
      }
    ]
  },
  {
    "city": "B",
    "street_values": [
      {
        "street": "a",
        "tenant_values": [
          {
            "tenant": "Smith",
            "income": "300"
          }
        ]
      },
      {
        "street": "b",
        "tenant_values": [
          {
            "tenant": "Jones",
            "income": "400"
          }
        ]
      }
    ]
  }
]

有没有更好的方法来做这件事?

那么,您是在询问有关从R输出JSON的问题,还是如何创建一个符合R定义的“嵌套列表”的R对象,例如foo<-list(bar=NA,snafu="hello, Dave"); foo[[bar]] <- list(a=1,b=2) - Carl Witthoft
我只是展示了JSON输出,因为它比R列表格式更容易理解,但我想从R数据框转换为R列表。 - nachocab
2个回答

9

您可以使用split方法完成大部分操作,然后使用rapply方法完成最后一步:

nestedList <- rapply(lapply(split(data[-1], data[1]), 
                            function(x) split(x[-1], x[1])), 
                     f = function(x) as.character(unlist(x)), 
                     how = "replace")

这是输出结果:
nestedList
# $A
# $A$a
# $A$a$tenant
# [1] "Smith"
# 
# $A$a$income
# [1] "100"
# 
# 
# $A$b
# $A$b$tenant
# [1] "Jones"
# 
# $A$b$income
# [1] "200"
# 
# 
# 
# $B
# $B$a
# $B$a$tenant
# [1] "Smith"
# 
# $B$a$income
# [1] "300"
# 
# 
# $B$b
# $B$b$tenant
# [1] "Jones"
# 
# $B$b$income
# [1] "400"

并且结构如下:

> str(nestedList)
List of 2
 $ A:List of 2
  ..$ a:List of 2
  .. ..$ tenant: chr "Smith"
  .. ..$ income: chr "100"
  ..$ b:List of 2
  .. ..$ tenant: chr "Jones"
  .. ..$ income: chr "200"
 $ B:List of 2
  ..$ a:List of 2
  .. ..$ tenant: chr "Smith"
  .. ..$ income: chr "300"
  ..$ b:List of 2
  .. ..$ tenant: chr "Jones"
  .. ..$ income: chr "400"

这个结构并不完全符合你想要的,但这可能有助于为另一种方法开个头。


1
我通过更改函数找到了解决我的问题的方法,代码如下:

nestedList <- rapply(lapply(split(df[-1], df[1]),
                          function(x) split(x[-1], x[1])),
                   f = function(x) as.data.frame(as.list(split(x,x))),  how = "replace")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接