我想在另一个列表中创建两个列表。通常,我必须为美国一个州每个创建50个,我正在寻找一种使之更快的方法。
State <- c("ALABAMA", "ALABAMA", "ALASKA", "ALASKA")
Num <- c(5, 6, 7, 8)
d <- data.frame(State, Num)
uni<-unique(d$State)
data = list(
for(i in 1 : length(uni)){
list[[i]](
name = un[i],
y = summarise(sum(d$Num[D$State==uni[i]])),
drilldown = tolower(un[i])
)
}
)
更具体地说,我希望每个列表在大写字母中包含name
的{{1}},State
作为y
和Num
的总和drilldown
的名称(非大写字母)。结果应该是这样的:
State
手动会是这样:
name="ALABAMA"
y= 11
drilldown="alabama"
name="ALASKA"
y= 15
drilldown="alaska"
给出了一个包含3个对象的2个列表的列表。
没有data = list(
list(
name = "ALABAMA",
y = 11,
drilldown = "alabama"
),
list(
name = "ALASKA",
y = 15,
drilldown = "alaska"
)
)
,这可能是可能的,所以我愿意接受其他建议
答案 0 :(得分:3)
State <- c("ALABAMA", "ALABAMA", "ALASKA", "ALASKA")
Num <- c(5, 6, 7, 8)
d <- data.frame(State, Num, stringsAsFactors = F)
解决方案1:Use built-in packages
df1 <- within(aggregate(Num ~ State, d, FUN = sum), drilldown <- tolower(State))
output1 <- lapply(split(df1, 1:nrow(df1)), c)
str(output1)
# List of 2
# $ 1:List of 3
# ..$ State : chr "ALABAMA"
# ..$ Num : num 11
# ..$ drilldown: chr "alabama"
# $ 2:List of 3
# ..$ State : chr "ALASKA"
# ..$ Num : num 15
# ..$ drilldown: chr "alaska"
解决方案2:library(tidyverse)
output2 <- d %>% group_by(State) %>%
summarise(Num = sum(Num)) %>%
mutate(drilldown = tolower(State)) %>%
transpose # purrr::transpose
str(output2)
# List of 2
# $ :List of 3
# ..$ State : chr "ALABAMA"
# ..$ Num : num 11
# ..$ drilldown: chr "alabama"
# $ :List of 3
# ..$ State : chr "ALASKA"
# ..$ Num : num 15
# ..$ drilldown: chr "alaska"
答案 1 :(得分:3)
您可以快速运行rowsum()
来获取组的总和,然后运行Map()
从列表的各个部分组合列表。
xx <- with(d, rowsum(Num, State))
Map(list, name=rownames(xx), y=xx, drilldown=tolower(rownames(xx)), USE.NAMES=FALSE)
# [[1]]
# [[1]]$name
# [1] "ALABAMA"
#
# [[1]]$y
# [1] 11
#
# [[1]]$drilldown
# [1] "alabama"
#
#
# [[2]]
# [[2]]$name
# [1] "ALASKA"
#
# [[2]]$y
# [1] 15
#
# [[2]]$drilldown
# [1] "alaska"
答案 2 :(得分:2)
您想要以下内容吗?它使用split
创建一个数据帧列表,每个State
一个,然后lapply
成为每个df的匿名函数。
这里有两个版本,具有不同的输出格式:"list"
类的对象和"data.frame"
类的对象。
lapply(split(d, d$State), function(DF){
s <- as.character(DF[["State"]][1])
list(
State = s,
y = sum(DF[["Num"]]),
drilldown = tolower(s)
)
})
lapply(split(d, d$State), function(DF){
s <- as.character(DF[["State"]][1])
data.frame(
State = s,
y = sum(DF[["Num"]]),
drilldown = tolower(s)
)
})
编辑。
第一种方法输出一个包含两个 named 列表的列表。如果要取消命名这些列表,请执行G. Grothendiek comment的建议。
data <-lapply(unname(split(d, d$State)), function(DF){
s <- as.character(DF[["State"]][1])
list(
State = s,
y = sum(DF[["Num"]]),
drilldown = tolower(s)
)
})
答案 3 :(得分:2)
在这里使用for循环确实不是最好的选择,因为它既缓慢又难以阅读。
对于使用管道的dplyr
软件包来说,这种任务是完美的:
library(dplyr)
df_result <- d %>%
group_by(State) %>%
summarise(y = sum(Num),
drilldown = tolower(first(State)))
print(df_result)
给予:
# A tibble: 2 x 3
State y drilldown
<fct> <dbl> <chr>
1 ALABAMA 11 alabama
2 ALASKA 15 alaska
如果您想获得示例输出中的嵌套列表而不是data.frame,则可以另外使用transpose()
包中的purrr
:
library(purrr)
transpose(df_result)
给予:
[[1]]
[[1]]$State
[1] "ALABAMA"
[[1]]$y
[1] 11
[[1]]$drilldown
[1] "alabama"
[[2]]
[[2]]$State
[1] "ALASKA"
[[2]]$y
[1] 15
[[2]]$drilldown
[1] "alaska"