簡體   English   中英

如何從具有不等維的列表列表的列表列中提取單個元素?

[英]How to extract single element from a tibble with a list column which is a list-of-lists with unequal dimensions?

我有一個帶有列表列的小標題。 該列表列中的每個元素都是一組命名的鍵​​值對,結構為兩個列表的列表。 鍵名為“CUSTOM_FIELD_ID”,值存儲在“FIELD_VALUE”下。

每行的對數和對的順序在小標題中有所不同。 我想用特定的鍵 ('CONTACT_FIELD_7') 和值 ('XYZ') 對搜索 tibble 中的行。

我的想法是以某種方式完全取消列表列的嵌套並向表格添加額外的行,以便每個鍵值對都有自己的行。 然后將兩個字符列添加到 tibble,一個用於鍵,一個用於值。 但是,然后我仍然留下一個包含兩個列表的列表列(現在每個列表中只有一個元素)。

我還試圖找到一種方法來搜索列表列表中的字符串。

這是輸入:

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' 可能根本沒有必要,因為可能有更有效的方法來做到這一點。 但是,沿着這條路徑,我能夠解開列表的最深層次,這會在 tibble 中創建額外的行,以在單獨的行中容納每個鍵值對。 我似乎無法擺脫長度為 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]> 

一種方法是使用purrr::keep將列表本身過濾為您關心的元素。 然后一個unnest將過濾到有東西的行,然后你可以把它變成一個 tibble,這樣它就可以整齊地取消嵌套。

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

或者,如果您想獲取所有內容並在最后使用filterbind_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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM