I have a dataframe that I want to convert to a nested list with a custom level of nesting. This is how I do it, but I'm sure there is a better way:
我有一个数据框,我想转换为嵌套列表与自定义嵌套级别。我就是这样做的,但我确信有更好的方法:
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)
}))
})
The output in JSON looks like:
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"
}
]
}
]
}
]
Is there a better way to do this?
有一个更好的方法吗?
2 个解决方案
#1
8
What about using split
to get you most of the way, and rapply
for the last step:
如何使用split来帮助你完成大部分工作,并为最后一步做好准备:
nestedList <- rapply(lapply(split(data[-1], data[1]),
function(x) split(x[-1], x[1])),
f = function(x) as.character(unlist(x)),
how = "replace")
Here's the output:
这是输出:
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"
And the structure:
结构:
> 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"
The structure doesn't exactly match what you're looking for, but this might help get you started with an alternative approach.
结构与您正在寻找的结构不完全匹配,但这可能有助于您开始使用其他方法。
#2
1
I found the solution of my question by changing the function as:
我通过将函数更改为:找到了我的问题的解决方案:
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")
#1
8
What about using split
to get you most of the way, and rapply
for the last step:
如何使用split来帮助你完成大部分工作,并为最后一步做好准备:
nestedList <- rapply(lapply(split(data[-1], data[1]),
function(x) split(x[-1], x[1])),
f = function(x) as.character(unlist(x)),
how = "replace")
Here's the output:
这是输出:
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"
And the structure:
结构:
> 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"
The structure doesn't exactly match what you're looking for, but this might help get you started with an alternative approach.
结构与您正在寻找的结构不完全匹配,但这可能有助于您开始使用其他方法。
#2
1
I found the solution of my question by changing the function as:
我通过将函数更改为:找到了我的问题的解决方案:
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")