我有一个列表列的小标题。该列表列中的每个元素都是一组命名的键-值对,结构为两个列表的列表。密钥称为“ CUSTOM_FIELD_ID”,其值存储在“ FIELD_VALUE”下。
每行的对数和对的顺序在小标题中有所不同。我想用特定的键('CONTACT_FIELD_7')和值('XYZ')对来搜索小标题中的行。
我的想法是完全以某种方式嵌套列表列,并在该文本框中添加其他行,以便每个键值对都有自己的行。然后将两列字符添加到小标题中,一列用于键,一列用于值。但是,我仍然留下一个带有两个列表的列表列(现在每个列表中只有一个元素)。
我还试图找到一种方法来搜索列表列表中的字符串。
这是输入:
library(tidyverse)
df_in <- tibble(CONTACT_ID = c(255381470, 255395936, 255400708, 255952013),
CUSTOMFIELDS = list(list(list('CUSTOM_FIELD_ID' = 'CONTACT_FIELD_7',
'FIELD_VALUE' = 'XYZ'),
list('CUSTOM_FIELD_ID' = 'CONTACT_FIELD_1',
'FIELD_VALUE' = '123')),
list(list('CUSTOM_FIELD_ID' = 'CONTACT_FIELD_2',
'FIELD_VALUE' = 'abc')),
list(list('CUSTOM_FIELD_ID' = 'CONTACT_FIELD_2',
'FIELD_VALUE' = 'def'),
list('CUSTOM_FIELD_ID' = 'CONTACT_FIELD_3',
'FIELD_VALUE' = '1234'),
list('CUSTOM_FIELD_ID' = 'CONTACT_FIELD_7',
'FIELD_VALUE' = 'XYZ')),
list(list('CUSTOM_FIELD_ID' = 'CONTACT_FIELD_1',
'FIELD_VALUE' = '456'),
list('CUSTOM_FIELD_ID' = 'CONTACT_FIELD_7',
'FIELD_VALUE' = 'ZYX'),
list('CUSTOM_FIELD_ID' = 'CONTACT_FIELD_5',
'FIELD_VALUE' = 'def'))))
# A tibble: 4 x 2
CONTACT_ID CUSTOMFIELDS
<dbl> <list>
1 255381470 <list [2]>
2 255395936 <list [1]>
3 255400708 <list [3]>
4 255952013 <list [3]>
我目前认为中间输出是
df_out_long <- tibble(CONTACT_ID = c(rep(255381470, 2), 255395936, rep(255400708, 3), rep(255952013, 3)),
CUSTOM_FIELD_ID = c('CONTACT_FIELD_7', 'CONTACT_FIELD_1', 'CONTACT_FIELD_2',
'CONTACT_FIELD_2', 'CONTACT_FIELD_3', 'CONTACT_FIELD_7',
'CONTACT_FIELD_1', 'CONTACT_FIELD_7', 'CONTACT_FIELD_5'),
FIELD_VALUE = c('XYZ', '123', 'abc', 'def', '1234', 'XYZ', '456', 'ZYX', 'def'))
# A tibble: 9 x 3
CONTACT_ID CUSTOM_FIELD_ID FIELD_VALUE
<dbl> <chr> <chr>
1 255381470 CONTACT_FIELD_7 XYZ
2 255381470 CONTACT_FIELD_1 123
3 255395936 CONTACT_FIELD_2 abc
4 255400708 CONTACT_FIELD_2 def
5 255400708 CONTACT_FIELD_3 1234
6 255400708 CONTACT_FIELD_7 XYZ
7 255952013 CONTACT_FIELD_1 456
8 255952013 CONTACT_FIELD_7 ZYX
9 255952013 CONTACT_FIELD_5 def
然后可以轻松过滤出最终所需的结果
df_out_long %>%
filter(CUSTOM_FIELD_ID == 'CONTACT_FIELD_7', FIELD_VALUE == 'XYZ')
CONTACT_ID CUSTOM_FIELD_ID FIELD_VALUE
<dbl> <chr> <chr>
1 255381470 CONTACT_FIELD_7 XYZ
2 255400708 CONTACT_FIELD_7 XYZ
上面的“ df_out_long”可能根本没有必要,因为可能有更有效的方法来执行此操作。但是,沿着这条路径,我可以取消嵌套列表的最深层次,从而在小标题中创建其他行以容纳单独行上的每个键值对。我似乎无法摆脱结果为长度2的列表的列表列,并以某种方式将其展平为两个字符列,即“ CUSTOM_FIELD_ID”和“ FIELD_VALUE”。
df_in %>%
mutate_if(is.list, simplify_all) %>%
unnest()
# A tibble: 9 x 2
CONTACT_ID CUSTOMFIELDS
<dbl> <list>
1 255381470 <list [2]>
2 255381470 <list [2]>
3 255395936 <list [2]>
4 255400708 <list [2]>
5 255400708 <list [2]>
6 255400708 <list [2]>
7 255952013 <list [2]>
8 255952013 <list [2]>
9 255952013 <list [2]>
答案 0 :(得分:1)
一种方法是使用purrr::keep
将列表本身过滤为仅关注的元素。然后,一个unnest
将过滤掉剩下的行,然后将其变成小标题,以便将其整齐地嵌套。
library(tidyverse)
df_discarded <- df_in %>% mutate(CUSTOMFIELDS = map(
CUSTOMFIELDS, keep,
~.x$CUSTOM_FIELD_ID == 'CONTACT_FIELD_7' && .x$FIELD_VALUE == 'XYZ'
))
df_discarded
#> # A tibble: 4 x 2
#> CONTACT_ID CUSTOMFIELDS
#> <dbl> <list>
#> 1 255381470 <list [1]>
#> 2 255395936 <list [0]>
#> 3 255400708 <list [1]>
#> 4 255952013 <list [0]>
df_filtered <- df_discarded %>% unnest()
df_filtered
#> # A tibble: 2 x 2
#> CONTACT_ID CUSTOMFIELDS
#> <dbl> <list>
#> 1 255381470 <list [2]>
#> 2 255400708 <list [2]>
df_out <- df_filtered %>%
mutate(CUSTOMFIELDS = map(CUSTOMFIELDS, as_tibble)) %>%
unnest()
df_out
#> # A tibble: 2 x 3
#> CONTACT_ID CUSTOM_FIELD_ID FIELD_VALUE
#> <dbl> <chr> <chr>
#> 1 255381470 CONTACT_FIELD_7 XYZ
#> 2 255400708 CONTACT_FIELD_7 XYZ
或者,如果您想掌握所有内容并最后使用filter
,则bind_rows
可以将命名列表变成小标题,然后将其取消嵌套:
df_in %>%
mutate(CUSTOMFIELDS = map(CUSTOMFIELDS, bind_rows)) %>%
unnest()
#> # A tibble: 9 x 3
#> CONTACT_ID CUSTOM_FIELD_ID FIELD_VALUE
#> <dbl> <chr> <chr>
#> 1 255381470 CONTACT_FIELD_7 XYZ
#> 2 255381470 CONTACT_FIELD_1 123
#> 3 255395936 CONTACT_FIELD_2 abc
#> 4 255400708 CONTACT_FIELD_2 def
#> 5 255400708 CONTACT_FIELD_3 1234
#> 6 255400708 CONTACT_FIELD_7 XYZ
#> 7 255952013 CONTACT_FIELD_1 456
#> 8 255952013 CONTACT_FIELD_7 ZYX
#> 9 255952013 CONTACT_FIELD_5 def