【问题标题】:R - split dataframe into list by column while retaining a second column, then rename list elements by col nameR - 将数据帧按列拆分为列表,同时保留第二列,然后按列名重命名列表元素
【发布时间】:2021-02-20 04:11:08
【问题描述】:

两个分开的问题。第一部分看起来很简单,但我一定错过了。 我想按列拆分数据框,但在这些数据中,请在每个列表元素中保留 state 列。

那么理想情况下,我想将列表元素重命名为列名,并将列表元素中的列名标准化。

更容易展示:

df <- data.frame(state = rep(letters[1:3], each = 2),
                 score1 = rnorm(6, 1, 1),
                 score2 = rnorm(6, 10, 1))

我最想得到的是

$`score1`
   state      value 
1      a  0.3406192
2      a  0.9598098
3      b  0.8813060
4      b  0.9803431
5      c  0.5143215
6      c -0.4401475 

$`score2`
   state      value
1      a  10.332035
2      a  11.572288
3      b  8.930529
4      b  10.916287
5      c  9.405007
6      c  12.181647

This SO post is very close 但我认为可能有更好的方法来保留 state 列,同时拆分其他列。

最终目标是将这些按状态嵌套到一个 tibble 中,汇总每个状态以获得平均值和 sd,然后使用purrr::map() 在每个上运行一系列模型(因此列名标准化)。如果有人提出一些建议,tidyverse 建议会很棒,但其他解决方案也很酷。

【问题讨论】:

  • 问题的措辞很糟糕,因此任何建议或为清晰起见的编辑都会非常有帮助!

标签: r


【解决方案1】:

获取长格式数据帧并使用split

library(tidyverse)

df %>%
  pivot_longer(cols = starts_with('score')) %>%
  split(.$name) %>%
  map(~.x %>% select(-name))

#$score1
# A tibble: 6 x 2
#  state  value
#  <chr>  <dbl>
#1 a      1.58 
#2 a      0.567
#3 b     -0.313
#4 b      0.756
#5 c      0.236
#6 c      1.05 

#$score2
# A tibble: 6 x 2
#  state value
#  <chr> <dbl>
#1 a      9.93
#2 a      9.96
#3 b     12.2 
#4 b      9.41
#5 c      9.40
#6 c      9.97

您也可以使用group_split 并避免map 步骤,但它不会在输出中给出列表名称(score1score2)。

df %>%
  pivot_longer(cols = starts_with('score')) %>%
  group_split(name, .keep  = FALSE)

【讨论】:

    【解决方案2】:

    基础 R 解决方案:

     # Reshape the data.frame to long format: long_df => data.frame
    long_df <- reshape(
      df,
      direction = "long",
      varying = which(names(df) != "state"),
      idvar = "state",
      v.names = "value",
      timevar = "score_no",
      times = names(df)[names(df) != "state"],
      new.row.names = seq_len((sum(names(df) != "state") * nrow(df)))
    )
    # Allocate some memory: df_list => empty list: 
    df_list <- vector("list", length(unique(long_df$score_no)))
    
    # Split the data.frame into a list: df_list => list of data.frames
    df_list <- split(long_df[,names(long_df) != "score_no"], long_df$score_no)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-20
      • 2015-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-30
      相关资源
      最近更新 更多