R语言 将数据框列转换为YAML中的字典数组

rbl8hiat  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(120)

我尝试从表格数据生成以下YAML结构:

- name: Josiah Carberry
  roles: 
    - investigation: lead 
    - data curation: supporting

字符串
我正在纠结roles键的结构,它基本上是一个字典数组,可以转换为R中的 Dataframe 列表。
我的问题是,我不知道如何存储这样的 Dataframe 列表,以产生与上面示例相同的输出。
以下是我的尝试:

library(tibble)

tibble(
  id = paste0("id", 1:2),
  roles = list(
    list(tibble(writing = "lead"), tibble(supervision = "supporting")),
    list(tibble(writing = "equal"))
  )
) |> 
  jsonlite::toJSON() |> 
  jsonlite::parse_json() |> 
  yaml::as.yaml(indent.mapping.sequence = TRUE) |> 
  cat()


它产生:

- id: id1
  roles:
    - - writing: lead
    - - supervision: supporting
- id: id2
  roles:
    - - writing: equal


正如您所看到的,由于我使用外部列表来存储 Dataframe ,因此每个角色之前都有一个额外的破折号。
你知道我怎样才能得到以下信息吗?

- id: id1
  roles:
    - writing: lead
    - supervision: supporting
- id: id2
  roles:
    - writing: equal

xmjla07d

xmjla07d1#

选项1:正则表达式

我不知道yaml::as.yaml第一次正确执行的方法,但您总是可以执行一个简单的gsub来手动更改所有- -

tibble(
  id = paste0("id", 1:2),
  roles = list(
    list(tibble(writing = "lead"), tibble(supervision = "supporting")),
    list(tibble(writing = "equal"))
  )
) |> 
  jsonlite::toJSON() |> 
  jsonlite::parse_json() |> 
  yaml::as.yaml(indent.mapping.sequence = TRUE) |>
  gsub("- - ", "- ", x = _) |>
  cat()
# - id: id1
#   roles:
#     - writing: lead
#     - supervision: supporting
# - id: id2
#   roles:
#     - writing: equal

字符串
如果您的某个项目中可能嵌入了合法的- -,则可以将gsub设置得更具体一些:

gsub("((^|\n) *)- - ", "\\1- ", x = _)


哪里

  • (^|\n)匹配字符串ninf(^)或嵌入的换行符;这是必要的,因为as.yaml返回一个嵌入了\n的字符串,所以我们不能依赖^来捕获所有字符串;我们总是可以使用strsplit(_, "\n")[[1]]来分割它,然后gsub再重新组合,但考虑到我们可以一步完成,这似乎是不必要的。
  • ((^|\n) *)查找上面加上零或更多的空格;我认为" "在这里是安全的,而不是"\\s",因为我相信as.yaml总是会在那里放空格;因为这是用括号 Package 的,它将作为一个模式组供以后调用
  • "\\1- "将模式中的所有内容(包括- -)替换为带括号的模式组(前一个项目符号)和一个连字符空格。

选项二:tibble转换为list

首先,这修复了上面的- -问题,尽管它转换了嵌套的内联字典。形式上,它们解析为相同的底层结构,所以如果你对增加的冗长没有意见,那么这可能更好:

tibble(
  id = paste0("id", 1:2),
  roles = list(
    list(tibble(writing = "lead"), tibble(supervision = "supporting")),
    list(tibble(writing = "equal"))
  )
) |> 
  transform(roles = rapply(roles, unlist, how = "list")) |>
  jsonlite::toJSON() |> 
  jsonlite::parse_json() |> 
  yaml::as.yaml(indent.mapping.sequence = TRUE) |> 
  cat()
# - id: id1
#   roles:
#     - writing:
#         - lead
#     - supervision:
#         - supporting
# - id: id2
#   roles:
#     - writing:
#         - equal


这看起来与您预期的略有不同,尽管它们仍然是有效的yaml字典。effective 结果通过以下方式确认:

out1 <- tibble(
  id = paste0("id", 1:2),
  roles = list(
    list(tibble(writing = "lead"), tibble(supervision = "supporting")),
    list(tibble(writing = "equal"))
  )
) |> 
  jsonlite::toJSON() |> 
  jsonlite::parse_json() |> 
  yaml::as.yaml(indent.mapping.sequence = TRUE) |>
  gsub("- - ", "- ", x = _)
out2 <- tibble(
  id = paste0("id", 1:2),
  roles = list(
    list(tibble(writing = "lead"), tibble(supervision = "supporting")),
    list(tibble(writing = "equal"))
  )
) |> 
  transform(roles = rapply(roles, unlist, how = "list")) |>
  jsonlite::toJSON() |> 
  jsonlite::parse_json() |> 
  yaml::as.yaml(indent.mapping.sequence = TRUE)

out1
# [1] "- id: id1\n  roles:\n    - writing: lead\n    - supervision: supporting\n- id: id2\n  roles:\n    - writing: equal\n"
out2
# [1] "- id: id1\n  roles:\n    - writing:\n        - lead\n    - supervision:\n        - supporting\n- id: id2\n  roles:\n    - writing:\n        - equal\n"
identical(yaml::read_yaml(text = out1), yaml::read_yaml(text = out2))
# [1] TRUE

相关问题