【问题标题】:Element of vector to different columns of data frame向量元素到数据框的不同列
【发布时间】:2018-02-23 23:31:42
【问题描述】:

我有一个 df:

   group number id
1      A   abcd  1
2      A   abcd  2
3      A   abcd  3
4      A   efgh  4
5      A   efgh  5
6      B   abcd  1
7      B   abcd  2
8      B   abcd  3
9      B   abcd  9
10     B   ijkl 10

我想变成这样:

   group number  data1 data2 data3 data4           Length
1      A   abcd      1     2     3                      3
2      A   efgh      4     5                            2
3      B   abcd      1     2     3     9                4
4      B   ijkl      10                                 1

很抱歉,我只能像这样进入 df2:

   group number     data               Length
1      A   abcd  c(1,2,3)                   3
2      A   efgh  c(4,5)                     2
3      B   abcd  c(1,2,3,9)                 4
4      B   ijkl  10                         1

我的代码在这里:

library(tidyverse)

df <- data.frame (group = c(rep('A',5),rep("B",5)),
                  number = c(rep('abcd',3),rep('efgh',2),rep('abcd',4),rep('ijkl',1)),
                  id = c(1,2,3,4,5,1,2,3,9,10))

df2 <- df %>%
  group_by(group,number) %>%
  nest() %>%
  mutate(data=map(data,~unlist(.x, recursive = TRUE, use.names = FALSE)),
         Length= map(data, ~length(.x)))

请随意从 df 或 df2 开始,任何包都可以。

【问题讨论】:

    标签: r dataframe vector tidyverse


    【解决方案1】:

    您可以将名称count更改为length(另外,我更喜欢将“空格”改为NA,如果要更改它,df2[is.na(df2)]=''


    选项 1

    df <- data.frame (group = c(rep('A',5),rep("B",5)),
                      number = c(rep('abcd',3),rep('efgh',2),rep('abcd',4),rep('ijkl',1)),
                      id = c(1,2,3,4,5,1,2,3,9,10))
    
    df2 <- df %>%
        group_by(group,number) %>%
        mutate(data=toString(id),count=n())
    
    library(splitstackshape)
    cSplit(df2, 3, drop = TRUE,sep=',')
    
    
       group number count data_1 data_2 data_3 data_4
    1:     A   abcd     3      1      2      3     NA
    2:     A   efgh     2      4      5     NA     NA
    3:     B   abcd     4      1      2      3      9
    4:     B   ijkl     1     10     NA     NA     NA
    

    选项 2

    library(dplyr)
    library(tidyr)
    
    df2 <- df %>%
         group_by(group,number) %>%
         summarise(data=toString(id),count=n())%>%separate_rows(data)%>% mutate(Col = paste0("data", 1:n()))%>%spread(Col, data)
    df2
    # A tibble: 4 x 8
    # Groups:   group [2]
       group number count data1 data2 data3 data4 data5
    * <fctr> <fctr> <int> <chr> <chr> <chr> <chr> <chr>
    1      A   abcd     3     1     2     3  <NA>  <NA>
    2      A   efgh     2  <NA>  <NA>  <NA>     4     5
    3      B   abcd     4     1     2     3     9  <NA>
    4      B   ijkl     1  <NA>  <NA>  <NA>  <NA>    10
    

    【讨论】:

    • 这似乎比下面@moody 的回答更脆弱。例如,考虑带有嵌入式,toString(c("1,","2","3")) 返回"1,, 2, 3"
    • @thelatemail 在这种情况下他的回答更好,对于我的回答,我从原始数据输入开始..;-)
    【解决方案2】:

    我必须盲目地把它给你,但这应该有效或接近:

    library(tidyverse)
    df %>%
        group_by(group,number) %>%
        mutate(key = paste0("data",row_number()),length = n()) %>%
        ungroup %>%
        spread(key,id,"")
    

    为了让它从您的嵌套数据中工作,我认为您必须将这些向量更改为 1 行 data.frames 相同的 col 编号和名称,然后使用 unnest,更复杂! :)

    【讨论】:

    • 这似乎是最明确的答案。我认为您可以避免使用ungroup,如果您在mutate 中添加一个额外的变量,您也可以在输出中获得长度变量——例如df %&gt;% group_by(group,number) %&gt;% mutate(rn=paste0("data",row_number()),length=n()) %&gt;% spread(rn, id)
    • 是的,我没有看到最后一列,谢谢 :)。你可以跳过取消组合,它打印得很好,但是你忘记了它是分组的,当你稍后重做你的桌子时你把它搞砸了:)。
    【解决方案3】:

    在基础 R

    temp = split(df, paste(df$group, df$number))
    columns = max(sapply(temp, NROW))
    do.call(rbind, lapply(temp, function(a)
        cbind(group = a$group[1],
              number = a$number[1],
              setNames(data.frame(t(a$id[1:columns])), paste0("data", 1:columns)),
              length = length(a$id))
    ))
    #       group number data1 data2 data3 data4 length
    #A abcd     A   abcd     1     2     3    NA      3
    #A efgh     A   efgh     4     5    NA    NA      2
    #B abcd     B   abcd     1     2     3     9      4
    #B ijkl     B   ijkl    10    NA    NA    NA      1 
    

    【讨论】:

    • 你也可以适应 @moody_mudskipper 在 dplyr 中所做的,并在基础 R 中使用 reshape - ids &lt;- c("group","number"); reshape(transform(df, time=ave(rep(1,nrow(df)), df[ids], FUN=seq_along)), idvar=ids, direction="wide", sep="") 或类似
    【解决方案4】:

    这是一个使用data.table的选项

    library(data.table)
    dcast(setDT(df), group + number~ paste0("data", rowid(group, number)), 
     value.var = 'id', fill = 0)[, 
       length := Reduce(`+`, lapply(.SD, `>`, 0)), .SDcols = data1:data4][]
    #    group number data1 data2 data3 data4 length
    #1:     A   abcd     1     2     3     0      3
    #2:     A   efgh     4     5     0     0      2
    #3:     B   abcd     1     2     3     9      4
    #4:     B   ijkl    10     0     0     0      1
    

    【讨论】:

      【解决方案5】:

      这是akrun's data.table answer 的变体,它计算Length 之前 从长格式到宽格式并在调用rowid() 时使用prefix 参数:

      library(data.table)
      
      data.table(df)[, Length := .N, by = .(group, number)][
        , dcast(.SD, group + number + Length ~ rowid(group, number, prefix = "data"), 
                value.var = "id")]
      
         group number Length data1 data2 data3 data4
      1:     A   abcd      3     1     2     3    NA
      2:     A   efgh      2     4     5    NA    NA
      3:     B   abcd      4     1     2     3     9
      4:     B   ijkl      1    10    NA    NA    NA
      

      为了漂亮的打印,NA 值可以转换为空白:

      data.table(df)[, Length := .N, by = .(group, number)][
        , dcast(.SD, group + number + Length ~ rowid(group, number, prefix = "data"), 
                as.character, value.var = "id", fill = "")]
      
         group number Length data1 data2 data3 data4
      1:     A   abcd      3     1     2     3      
      2:     A   efgh      2     4     5            
      3:     B   abcd      4     1     2     3     9
      4:     B   ijkl      1    10
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-07-05
        • 2019-11-04
        • 2021-04-30
        • 2022-08-03
        • 2023-03-23
        • 2020-10-20
        • 2018-09-20
        • 2017-02-25
        相关资源
        最近更新 更多