瑞士JSON处理刀

如何在R中有效使用json?


它是以前出版物的延续。


问题陈述


通常,JSON格式的主要数据源是REST API。 除了平台独立性和人对数据感知的便利性之外,使用json还可以交换具有复杂树结构的非结构化数据系统。


在构建API的任务中,这非常方便。 易于确保通信协议的版本,易于提供信息交换的灵活性。 同时,数据结构的复杂性(嵌套级别可以为5、6、10甚至更​​高)并不可怕,因为为单个记录编写一个灵活的解析器时要考虑到所有问题,并不是那么困难。


数据处理任务还包括从外部资源获取数据,包括 以json格式。 R有一套不错的软件包,特别是jsonlite ,旨在将json转换为R对象( listdata.frame ,如果数据结构允许)。


但是,在实践中,当使用jsonlite时,经常会出现两类问题,类似的问题变得效率极低。 任务看起来像这样:


  • 处理在各种信息系统运行期间获得的大量数据(度量单位-千兆字节);
  • 将在参数化REST API请求数据包期间收到的大量可变结构响应组合成统一的矩形表示形式( data.frame )。

插图中类似结构的示例:


图片


图片


为什么这些任务类有问题?


大量数据


通常,以json格式从信息系统中卸载是不可分割的数据块。 要正确解析它,您需要阅读所有内容并遍历整个卷。


引起的问题:


  • 需要相应数量的RAM和计算资源;
  • 解析速度在很大程度上取决于所使用的库的质量,即使有足够的资源,转换时间也可能是数十分钟甚至数百分钟。
  • 在解析失败的情况下,输出不会获得结果,也没有理由希望一切都会一直顺利进行,没有理由,相反则相反;
  • 如果将解析后的数据可以转换为data.frame那将是非常成功的。

合并树结构


例如,当需要通过API通过请求包收集业务流程所需的目录以进行工作时,就会出现类似的任务。 此外,目录意味着可以统一并准备好嵌入分析管道中,并有可能上载到数据库中。 而且这再次使得有必要将此类摘要数据转换为data.frame


引起的问题:


  • 树结构本身不会变成平坦的。 json解析器将输入数据转换为一组嵌套列表,然后需要长时间手动部署它们,这很痛苦。
  • 输出数据属性的自由(可能不显示)可能导致出现与列表相关的NULL对象,但不能“适合” data.frame ,这进一步使后处理复杂化,甚至使合并单张纸行的基本过程也变得复杂。 data.frame (与rbindlistbind_rows ,'map_dfr'或rbind无关)。

JQ出路


在特别困难的情况下,由于上述原因,使用非常方便的jsonlite包“将所有内容转换为R对象”的方法会造成严重的故障。 好吧,如果您设法结束处理。 更糟糕的是,如果在中间,您必须张开双臂放弃。


此方法的替代方法是使用json预处理器,该预处理器直接对json数据进行操作。 jq库和jqr包装器。 实践表明,它不仅很少使用,而且很少有人听说过,而且是徒劳的。


jq库的好处。


  • 该库可以在R,Python和命令行中使用;
  • 所有转换都在json级别执行,而无需转换为R / Python对象的表示形式;
  • 处理可以分为原子操作和使用链(管道)的原理;
  • 处理对象向量的周期隐藏在解析器内部,最大限度地简化了迭代语法;
  • 能够执行所有程序以统一json结构,部署和选择必要的元素,以创建json格式,并使用jsonlite将其以批处理方式转换为jsonlite
  • 负责处理json数据的R代码的多次缩减;
  • 巨大的处理速度,取决于数据结构的数量和复杂性,增益可以为1-3个数量级;
  • 更少的RAM需求。

处理代码被压缩以适合屏幕,并且可能看起来像这样:


 cont <- httr::content(r3, as = "text", encoding = "UTF-8") m <- cont %>% #     jqr::jq('del(.[].movie.rating, .[].movie.genres, .[].movie.trailers)') %>% jqr::jq('del(.[].movie.countries, .[].movie.images)') %>% #     jqr::jq('del(.[].schedules[].hall, .[].schedules[].language, .[].schedules[].subtitle)') %>% #     jqr::jq('del(.[].cinema.location, .[].cinema.photo, .[].cinema.phones)') %>% jqr::jq('del(.[].cinema.goodies, .[].cinema.subway_stations)') #  m2 <- m %>% jqr::jq('[.[] | {date, movie, schedule: .schedules[], cinema}]') df <- fromJSON(m2) %>% as_tibble() 

jq非常优雅,快捷! 对于那些与之相关的人:下载,设置,理解。 我们加快处理速度,简化自己和同事的生活。


上一篇文章- “如何开始在企业中应用R。 一个实用方法的例子

Source: https://habr.com/ru/post/zh-CN448950/


All Articles