添加标识符适合多种模式的列

Add columns where identifiers fit multiple patterns

数据框 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_ntz == 3 处)调用 id0 的每个值一个“big id”,每个值不不适合这个模式“little id。”上面的12个obs包括三个大idrowafj)。对于每个 big id,我需要:

  1. 查找 id0 的所有其他值,这些值与第 i 前三位数字 相匹配大id
  2. 将每个匹配项的 id0 的值添加到称为 idjj 个离散向量之一,其中 j 是一个范围从 1 到 j 的后缀,它有效地统计了嵌套在 i[= 中的匹配 little ids 的数量62=第大id.

如果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

我对任何动态解决此问题的解决方案持开放态度(即,与 大 ID小 ID[=58= 的数量无关],以及生成的 idj 个向量)。

P.S.: 我需要在 id0_ntz == 2,然后 1 处再次做同样的事情,但是这个已发布问题的可接受答案只需要解决问题的解决方案其中 id0_ntz == 3.

这将达到您的目的

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-05-28 创建
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-05-27 创建

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

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-05-27 创建