如何将多层嵌套列表转换为一个 tibble 以避免在使用 filter 时出现错误?

huangapple go评论79阅读模式
英文:

How to change a multi-level nested list into a tibble to avoid an error with filter?

问题

在一个具有三个层级的嵌套列表中,我需要到达第三个层级(即资源)并检查数据中是否存在一些特殊字符。我尝试创建了类似的数据示例,但仍然存在无法解决的差异。虽然第一级(foo)和第二级(例如,obj1)是列表,但第三级(资源)是list(s3:data.frame)。我运行了下面的代码,但如您所见,在第二部分(即筛选)时出现错误。请问如何避免这个错误?

obj1 <- list(resource = list(bodyPart = c("leg", "arm", "knee"), side = "RIGHT", device = "SENS"))
obj2 <- list(resource = list(bodyPart = c("leg", "arm", "knee"), side = "LEFT", device = "GOM"))

x <- list(foo = obj1, bar = obj2)

Dat <- lapply(x, function(tb) tb[sapply(tb, function(z) any(grepl("[^\x01-\x7F]", z), na.rm = TRUE))]) %>%
  dplyr::filter(if_any(everything(), ~ grepl("[^\x01-\x7F]", .)))

Error in UseMethod("filter") : 
  no applicable method for 'filter' applied to an object of class "list"
英文:

In a nested list with three levels, I need to reach the third level (i.e., resources) and check whether some special characters exist in the data. I tried to make a similar sample of data but there is still a difference I could not address. While level1 (foo) and level 2 (e.g., obj1) are lists, level 3 (resource) is list(s3:data.frame). I run the code below but as you can see there is an error when it comes to the second part (i.e., filter). Could you please tell me how to avoid this error?

    obj1 &lt;- list(resource = list(bodyPart = c(&quot;leg&quot;, &quot;arm&quot;, &quot;knee&quot;),side = &quot;RIGHT&quot;, device = &quot;SENS&quot;))
    obj2 &lt;- list(resource = list(bodyPart = c(&quot;leg&quot;, &quot;arm&quot;, &quot;knee&quot;), side = &quot;LEFT&quot;, device = &quot;GOM&quot;))
        
    x &lt;- list(foo = obj1, bar = obj2)
        
Dat &lt;- lapply(x, function(tb) tb[sapply(tb, function(z) any(grepl(&quot;[^\x01-\x7F]&quot;, z), na.rm = TRUE))]) %&gt;% 
dplyr::filter(if_any(everything(), ~ grepl(&quot;[^\x01-\x7F]&quot;, .)))
        
        Error in UseMethod(&quot;filter&quot;) : 
          no applicable method for &#39;filter&#39; applied to an object of class &quot;list&quot;

答案1

得分: 0

你可以使用 rapply 递归扫描列表节点:

x |&gt; rapply(f = \(node) grepl(&quot;[^\x01-\x7F]&quot;, node))

生成上述的 tibble:

library(tibble)

data.frame(has_invalid_character = x |&gt; rapply(f = \(node) grepl(&quot;[^\x01-\x7F]&quot;, node)),
           content =  x |&gt; rapply(f = \(node) node)
           ) |&gt;
  rownames_to_column(&#39;item&#39;) |&gt;
  as_tibble()
# A tibble: 10 x 3
   item                   has_invalid_character content
   &lt;chr&gt;                  &lt;lgl&gt;                 &lt;chr&gt;  
 1 foo.resource.bodyPart1 FALSE                 leg    
 2 foo.resource.bodyPart2 FALSE                 arm    
 3 foo.resource.bodyPart3 FALSE                 knee   
 4 foo.resource.side      FALSE                 RIGHT  
 5 foo.resource.device    FALSE                 SENS        
## etc.
英文:

you could recursively scan the list nodes with rapply:

x |&gt; rapply(f = \(node) grepl(&quot;[^\x01-\x7F]&quot;, node))

to generate a tibble from above:

library(tibble)

data.frame(has_invalid_character = x |&gt; rapply(f = \(node) grepl(&quot;[^\x01-\x7F]&quot;, node)),
           content =  x |&gt; rapply(f = \(node) node)
           ) |&gt;
  rownames_to_column(&#39;item&#39;) |&gt;
  as_tibble()
# A tibble: 10 x 3
   item                   has_invalid_character content
   &lt;chr&gt;                  &lt;lgl&gt;                 &lt;chr&gt;  
 1 foo.resource.bodyPart1 FALSE                 leg    
 2 foo.resource.bodyPart2 FALSE                 arm    
 3 foo.resource.bodyPart3 FALSE                 knee   
 4 foo.resource.side      FALSE                 RIGHT  
 5 foo.resource.device    FALSE                 SENS        
## etc.

huangapple
  • 本文由 发表于 2023年5月24日 18:49:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/76322702.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定