使用循环在另一个列表中创建列表

时间:2019-02-24 14:43:57

标签: r

我想在另一个列表中创建两个列表。通常,我必须为美国一个州每个创建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作为yNum的总和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" ) ) ,这可能是可能的,所以我愿意接受其他建议

4 个答案:

答案 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"