【问题标题】:R how to 'spread' data with no key-value pairR如何在没有键值对的情况下“传播”数据
【发布时间】:2019-01-13 10:43:19
【问题描述】:

我有数据:

rowID    incidentID participant.type
1          1                A
2          1                B
3          2                A
4          3                A
5          3                B
6          3                C
7          4                B
8          4                C

我想最终得到:

   rowID incident participant.type participant.type.1 participant.type.2
    1        1                A                  B                   
    2        2                A                                      
    3        3                A                  B                  C
    4        4                B                  C      

我尝试了传播,但无法实现每个事件一行;我认为我没有创建键值对的方法,所以我想知道是否有其他方法可以做到这一点。

【问题讨论】:

标签: r tidyr


【解决方案1】:

在使用spread() 之前,您需要创建一个正确的key 参数。

df %>% select(-rowID) %>%
       group_by(incidentID) %>%
       mutate(id = 1:n()) %>%
       spread(id, participant.type)

#   incidentID  `1`   `2`   `3`  
#        <int>  <fct> <fct> <fct>
# 1          1  A     B     NA   
# 2          2  A     NA    NA   
# 3          3  A     B     C    
# 4          4  B     C     NA 

【讨论】:

  • 这是最好的解决方案。
【解决方案2】:

因为您的分组是基于 icidentID 列中的行顺序。以下简单的解决方案也可以使用。

它只是过滤数据框,然后最后合并。

就计算能力的有效利用而言,这可能不是最好的解决方案,但它很容易理解。

library(tidyverse)

df <- 
  tribble(
    ~rowID,    ~incidentID, ~participant.type,
    1,          1,                "A",
    2,          1,                "B",
    3,          2,                "A",
    4,          3,                "A",
    5,          3,                "B",
    6,          3,                "C",
    7,          4,                "B",
    8,          4,                "C")

df_1 <- df %>%
  select(-rowID) %>% 
  group_by(incidentID) %>% 
  filter(row_number()==1)


df_2 <- df %>%
  select(-rowID) %>% 
  group_by(incidentID) %>% 
  filter(row_number()==2) %>% 
  rename(participant.type.1 = participant.type)


df_3 <- df %>%
  select(-rowID) %>% 
  group_by(incidentID) %>% 
  filter(row_number()==3) %>% 
  rename(participant.type.2 = participant.type) 

full_join(df_1, full_join(df_2, df_3))

结果:

Joining, by = "incidentID"
Joining, by = "incidentID"
# A tibble: 4 x 4
# Groups:   incidentID [?]
  incidentID participant.type participant.type.1 participant.type.2
       <dbl> <chr>            <chr>              <chr>             
1          1 A                B                  NA                
2          2 A                NA                 NA                
3          3 A                B                  C                 
4          4 B                C                  NA    

【讨论】:

    【解决方案3】:

    这是我的解决方案:

    df %>%
      select(-rowID) %>%
      group_by(incidentID) %>%
      nest() %>%
      mutate(data = map_chr(data, ~str_c(.x$participant.type, collapse = '_'))) %>%
      separate(data, paste0('participant.type.', 0:2)) %>%
      mutate_at(2:4, ~replace_na(.x, ''))
    

    【讨论】:

      【解决方案4】:

      我们可以为此使用reshape2::dcast

      reshape2::dcast(df, insidentID ~ participant.type)    
        #   insidentID    A    B    C
        # 1          1 <NA>    B <NA>
        # 2          8 <NA>    B <NA>
        # 3         12 <NA> <NA>    C
        # 4         16    A <NA> <NA>
        # 5         24 <NA>    B <NA>
        # 6         27 <NA>    B    C
        # 7         29 <NA> <NA>    C
      

      数据

      set.seed(123)
      df <- data.frame(insidentID = sample(0:30, 8L, replace = TRUE),
                       participant.type = sample(LETTERS[1:3], 8L, replace = TRUE),
                       stringsAsFactors = FALSE)
      df
      #   insidentID participant.type
      # 1          8                B
      # 2         24                B
      # 3         12                C
      # 4         27                B
      # 5         29                C
      # 6          1                B
      # 7         16                A
      # 8         27                C
      

      【讨论】:

        【解决方案5】:

        @markus 提供的“相关问题”链接显示了各种其他解决方案,包括最简洁的 tidyverse 格式:

         df %>% 
          group_by(incidentID) %>%
          mutate(rn = paste0("newcolumn",row_number()))  %>%
          spread(rn, participant.type)
        

        给予:

        incidentID newcolumn1 newcolumn2 newcolumn3
               <int> <fct>      <fct>      <fct>     
        1          1 A          B          NA        
        2          2 A          NA         NA        
        3          3 A          B          C         
        4          4 B          C          NA
        

        一个

        【讨论】:

        • 如果您不删除变量rowID,输出将不是您上面显示的内容。你的解决方案和我的一样。您无需再次发布。
        • 感谢您的帮助,我想我在看到您的链接之前已根据链接发布了代码。我已将您的标记为解决方案。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-04
        • 1970-01-01
        • 1970-01-01
        • 2019-08-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多