【问题标题】:Add columns where identifiers fit multiple patterns添加标识符适合多种模式的列
【发布时间】:2021-08-15 22:58:39
【问题描述】:

一个数据框df 对于其数字向量id0 的每个不同值都有一行 - 但id0 的单元格中的尾随零表示必须沿其转换文件的重要组。以下是对df 的 12 条观察:

row id0     id0_ntz
a   111000  3
b   111010  1
c   112345  0
d   111974  0
e   112090  1
f   114000  3
g   114099  0
h   555001  0
i   555012  0
j   461000  3
k   461020  1
l   111090  0

让我们将id0 的每个值都用三个尾随零(即id0_ntz == 3)称为“big id”,将每个不符合此模式的值称为“小身份证。”上面的 12 个 obs 包括三个 big idrowafj)。对于每个 big id,我需要:

  1. 查找与第 ibig id前三位相匹配的 id0 的所有其他值
  2. 将每次匹配的id0 的值添加到称为idjj 个离散向量之一,其中j 是从1 到 的后缀j 有效地计算嵌套在第 ibig id 中的匹配 little ids 的数量。

如果df 只包括上面显示的 12 行,正确的结果应该是这样的:

row id0     id0_ntz id1     id2     id3
a   111000  3       111010  111974  111090
b   111010  1       NA      NA      NA
c   112345  0       NA      NA      NA
d   111974  0       NA      NA      NA
e   112090  1       NA      NA      NA
f   114000  3       114099  NA      NA
g   114099  0       NA      NA      NA
h   555001  0       NA      NA      NA
i   555012  0       NA      NA      NA
j   461000  3       461020  NA      NA
k   461020  1       NA      NA      NA
l   111090  0       NA      NA      NA

我对任何动态解决此问题的解决方案持开放态度(即,与 big idslittle ids 的数量以及由此产生的 idj 向量的数量无关)。

P.S.:我需要在 id0_ntz == 21 处再次做同样的事情,但对这个已发布问题的可接受答案只需要解决 id0_ntz == 3 处的问题的解决方案。

【问题讨论】:

  • 似乎df[1,6] 是错误/错字? id0 中没有 111090 吗?
  • 这不是错字 - 111090 出现在 df[12,2]

标签: r loops apply data-manipulation data-cleaning


【解决方案1】:

这将达到你的目的

df <- read.table(text = 'row id0     id0_ntz
a   111000  3
b   111010  1
c   112345  0
d   111974  0
e   112090  1
f   114000  3
g   114099  0
h   555001  0
i   555012  0
j   461000  3
k   461020  1
l   111090  0', header = T)
df$id0 <- as.character(df$id0)
library(tidyverse)
df %>%
  filter(id0_ntz == 3) %>%
  mutate(big_id = substr(id0, 1, 3)) -> big_id

df %>% mutate(id0 = as.character(id0)) %>%
  left_join(df %>% mutate(id = as.character(id0),
                          dummy = match(substr(id, 1, 3), big_id$big_id)) %>%
              filter(!is.na(dummy)) %>%
              group_by(dummy) %>%
              mutate(d2 = paste0('id', row_number() - 1)) %>% select(-id0) %>%
              pivot_wider(id_cols = dummy, names_from = d2, values_from = id),
            by = c('id0')) %>%
  select(-dummy)
#>    row    id0 id0_ntz    id1    id2    id3
#> 1    a 111000       3 111010 111974 111090
#> 2    b 111010       1   <NA>   <NA>   <NA>
#> 3    c 112345       0   <NA>   <NA>   <NA>
#> 4    d 111974       0   <NA>   <NA>   <NA>
#> 5    e 112090       1   <NA>   <NA>   <NA>
#> 6    f 114000       3 114099   <NA>   <NA>
#> 7    g 114099       0   <NA>   <NA>   <NA>
#> 8    h 555001       0   <NA>   <NA>   <NA>
#> 9    i 555012       0   <NA>   <NA>   <NA>
#> 10   j 461000       3 461020   <NA>   <NA>
#> 11   k 461020       1   <NA>   <NA>   <NA>
#> 12   l 111090       0   <NA>   <NA>   <NA>

reprex package (v2.0.0) 于 2021 年 5 月 28 日创建

【讨论】:

    【解决方案2】:

    我会使用下面的方法。很短。

    library(tidyverse)
    
    df %>% 
      group_by(big_id = substr(id0, 1, 3)) %>% 
      mutate(id = ifelse(substr(id0, 4, 6) == "000",
                         list(setdiff(unique(id0),
                                      paste0(big_id, "000"))),
                         list())) %>% 
      unnest_wider(col = id,
                   names_sep = "")
    
    #> # A tibble: 12 x 7
    #> # Groups:   big_id [5]
    #>    row      id0 id0_ntz big_id    id1    id2    id3
    #>    <chr>  <int>   <int> <chr>   <int>  <int>  <int>
    #>  1 a     111000       3 111    111010 111974 111090
    #>  2 b     111010       1 111        NA     NA     NA
    #>  3 c     112345       0 112        NA     NA     NA
    #>  4 d     111974       0 111        NA     NA     NA
    #>  5 e     112090       1 112        NA     NA     NA
    #>  6 f     114000       3 114    114099     NA     NA
    #>  7 g     114099       0 114        NA     NA     NA
    #>  8 h     555001       0 555        NA     NA     NA
    #>  9 i     555012       0 555        NA     NA     NA
    #> 10 j     461000       3 461    461020     NA     NA
    #> 11 k     461020       1 461        NA     NA     NA
    #> 12 l     111090       0 111        NA     NA     NA
    

    reprex package (v0.3.0) 于 2021 年 5 月 27 日创建

    【讨论】:

      【解决方案3】:
      library(tidyverse)
      df <- read.table(text = 'row id0     id0_ntz
      a   111000  3
      b   111010  1
      c   112345  0
      d   111974  0
      e   112090  1
      f   114000  3
      g   114099  0
      h   555001  0
      i   555012  0
      j   461000  3
      k   461020  1
      l   111090  0', header = T)
      
      df %>% 
        mutate(id = id0 %/% 1000 * 1000) %>% 
        group_by(id) %>% 
        mutate(row_id = row_number() - 1) %>% 
        ungroup() %>% 
        filter(row_id != 0) %>% 
        pivot_wider(id, names_from = row_id, values_from = id0, names_prefix = "id") %>% 
        right_join(df, by = c("id" = "id0")) %>% 
        rename(id0 = id) %>% 
        arrange(row)
      #> # A tibble: 12 x 6
      #>       id0    id1    id2    id3 row   id0_ntz
      #>     <dbl>  <int>  <int>  <int> <chr>   <int>
      #>  1 111000 111010 111974 111090 a           3
      #>  2 111010     NA     NA     NA b           1
      #>  3 112345     NA     NA     NA c           0
      #>  4 111974     NA     NA     NA d           0
      #>  5 112090     NA     NA     NA e           1
      #>  6 114000 114099     NA     NA f           3
      #>  7 114099     NA     NA     NA g           0
      #>  8 555001     NA     NA     NA h           0
      #>  9 555012     NA     NA     NA i           0
      #> 10 461000 461020     NA     NA j           3
      #> 11 461020     NA     NA     NA k           1
      #> 12 111090     NA     NA     NA l           0
      

      reprex package (v2.0.0) 于 2021 年 5 月 27 日创建

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-06-05
        • 2016-10-13
        • 1970-01-01
        • 2011-02-27
        • 1970-01-01
        • 1970-01-01
        • 2023-03-10
        相关资源
        最近更新 更多