使用 R 解析其中键和值是数值的类似字典的结构
Parse dictionary-like structure in which key and values are numeric values using R
我正在尝试解析我在旅行中遇到的一些奇怪的数据结构。本质上它们类似于 python 或 javascript 字典,但键和值都是数字:
weird <- "{47=4578.0005, 181=23456.7831, 216=7548.2367}"
为了将其转换为 table,我尝试将其转换为更典型的字典格式并使用 jsonlite
进行解析:
library(tidyverse)
library(jsonlite)
weird <- parse_json(str_replace(weird, "=", ":"))
#> Error: parse error: invalid object key (must be a string)
parse_json
函数正确地抱怨密钥不是字符串。我当然可以使用 str_split
剖析所有这些,但我希望善良的人可能对更多 elegant/compact 解决方案有一些洞察力(希望完全避免正则表达式),可以将其解析为 table 这样:
tibble::tribble(
~ key, ~ value,
47, 4578.0005,
181, 23456.7831,
216, 7548.2367
)
#> # A tibble: 3 x 2
#> key value
#> <dbl> <dbl>
#> 1 47 4578.
#> 2 181 23457.
#> 3 216 7548.
谢谢!
JSON 要求引用其字典键。虽然此解决方案也引用了值,但将 as.numeric
应用于值应该不难(如果您确定数据语料库)。
library(dplyr)
library(tidyr)
gsub("=", ":", gsub("(\b|-?)([0-9.]+)\b", '"\1"', weird)) %>%
jsonlite::fromJSON(.) %>%
enframe() %>%
unnest(value)
# # A tibble: 3 x 2
# name value
# <chr> <chr>
# 1 47 4578.0005
# 2 181 23456.7831
# 3 216 7548.2367
这假设所有的键和值都是完全数字的(可能是负数,可能是小数),但在此模式中没有科学记数法。将其包括在内并非不可能,因此如果您需要更进一步:https://www.regular-expressions.info/floatingpoint.html, Parsing scientific notation sensibly?, and Regex for numbers on scientific notation? 可能会有所帮助。
下一步可能很简单
gsub("=", ":", gsub("(\b|-?)([0-9.]+)\b", '"\1"', weird)) %>%
jsonlite::fromJSON(.) %>%
enframe() %>%
unnest(value) %>%
mutate_all(as.numeric)
# # A tibble: 3 x 2
# name value
# <dbl> <dbl>
# 1 47 4578.
# 2 181 23457.
# 3 216 7548.
(明显丢失小数位只是表象,原始数据仍然有非整数值。)
虽然您可能想要一个紧凑的非正则表达式版本,但对我来说这似乎是最容易理解和易于理解的:
library(stringr)
library(dplyr)
weird <- "{47=4578.0005, 181=23456.7831, 216=7548.2367}"
str_remove_all(weird, "[{}]") %>%
str_split(", ", simplify = TRUE) %>%
str_split("=", simplify = TRUE) %>%
as_tibble() %>%
mutate_all(as.numeric)
#> # A tibble: 3 x 2
#> V1 V2
#> <dbl> <dbl>
#> 1 47 4578.
#> 2 181 23457.
#> 3 216 7548.
由 reprex package (v0.3.0)
于 2020 年 4 月 20 日创建
我不介意对数据进行三遍,每一步只完成一件事。我发现它更容易阅读和推理。
更新:
虽然我仍然认为上面的版本是 R 惯用的方法,但它不是 R 惯用的数据结构,所以这是通过 {reticulate}
使用 Python 的解决方案。这比使用 {jsonlite}
的 JSON 解析器要复杂一些,但事实证明您可以使用数值作为 Python 字典中的键。
我们首先必须将 =
转换为 :
然后字符串成为有效的字典。然后我们可以启动一个 Python 上下文,运行 一个字符串,将其分配给一个变量,然后 return 将状态分配给 R。然后它只是将 R 中的列表转换为数据帧。
library(reticulate)
library(stringr)
library(glue)
library(tibble)
weird <- '{47=4578.0005, 181=23456.7831, 216=7548.2367}'
weird <- str_replace_all(weird, "=", ": ")
x <- py_run_string(
glue("weird_dict = {weird}"),
convert = T
)
x$weird_dict %>%
unlist() %>%
enframe()
#> # A tibble: 3 × 2
#> name value
#> <chr> <dbl>
#> 1 47 4578.
#> 2 181 23457.
#> 3 216 7548.
由 reprex package (v2.0.1)
于 2021-10-21 创建
我不认为你可以完全避免正则表达式,但通过一些小的替换它可以被 read.table()
轻松阅读。
wt <- c("{47=4578.0005, 181=23456.7831, 216=7548.2367}")
read.table(text = gsub("[{},]", "\n", wt), sep = "=")
V1 V2
1 47 4578.001
2 181 23456.783
3 216 7548.237
我正在尝试解析我在旅行中遇到的一些奇怪的数据结构。本质上它们类似于 python 或 javascript 字典,但键和值都是数字:
weird <- "{47=4578.0005, 181=23456.7831, 216=7548.2367}"
为了将其转换为 table,我尝试将其转换为更典型的字典格式并使用 jsonlite
进行解析:
library(tidyverse)
library(jsonlite)
weird <- parse_json(str_replace(weird, "=", ":"))
#> Error: parse error: invalid object key (must be a string)
parse_json
函数正确地抱怨密钥不是字符串。我当然可以使用 str_split
剖析所有这些,但我希望善良的人可能对更多 elegant/compact 解决方案有一些洞察力(希望完全避免正则表达式),可以将其解析为 table 这样:
tibble::tribble(
~ key, ~ value,
47, 4578.0005,
181, 23456.7831,
216, 7548.2367
)
#> # A tibble: 3 x 2
#> key value
#> <dbl> <dbl>
#> 1 47 4578.
#> 2 181 23457.
#> 3 216 7548.
谢谢!
JSON 要求引用其字典键。虽然此解决方案也引用了值,但将 as.numeric
应用于值应该不难(如果您确定数据语料库)。
library(dplyr)
library(tidyr)
gsub("=", ":", gsub("(\b|-?)([0-9.]+)\b", '"\1"', weird)) %>%
jsonlite::fromJSON(.) %>%
enframe() %>%
unnest(value)
# # A tibble: 3 x 2
# name value
# <chr> <chr>
# 1 47 4578.0005
# 2 181 23456.7831
# 3 216 7548.2367
这假设所有的键和值都是完全数字的(可能是负数,可能是小数),但在此模式中没有科学记数法。将其包括在内并非不可能,因此如果您需要更进一步:https://www.regular-expressions.info/floatingpoint.html, Parsing scientific notation sensibly?, and Regex for numbers on scientific notation? 可能会有所帮助。
下一步可能很简单
gsub("=", ":", gsub("(\b|-?)([0-9.]+)\b", '"\1"', weird)) %>%
jsonlite::fromJSON(.) %>%
enframe() %>%
unnest(value) %>%
mutate_all(as.numeric)
# # A tibble: 3 x 2
# name value
# <dbl> <dbl>
# 1 47 4578.
# 2 181 23457.
# 3 216 7548.
(明显丢失小数位只是表象,原始数据仍然有非整数值。)
虽然您可能想要一个紧凑的非正则表达式版本,但对我来说这似乎是最容易理解和易于理解的:
library(stringr)
library(dplyr)
weird <- "{47=4578.0005, 181=23456.7831, 216=7548.2367}"
str_remove_all(weird, "[{}]") %>%
str_split(", ", simplify = TRUE) %>%
str_split("=", simplify = TRUE) %>%
as_tibble() %>%
mutate_all(as.numeric)
#> # A tibble: 3 x 2
#> V1 V2
#> <dbl> <dbl>
#> 1 47 4578.
#> 2 181 23457.
#> 3 216 7548.
由 reprex package (v0.3.0)
于 2020 年 4 月 20 日创建我不介意对数据进行三遍,每一步只完成一件事。我发现它更容易阅读和推理。
更新:
虽然我仍然认为上面的版本是 R 惯用的方法,但它不是 R 惯用的数据结构,所以这是通过 {reticulate}
使用 Python 的解决方案。这比使用 {jsonlite}
的 JSON 解析器要复杂一些,但事实证明您可以使用数值作为 Python 字典中的键。
我们首先必须将 =
转换为 :
然后字符串成为有效的字典。然后我们可以启动一个 Python 上下文,运行 一个字符串,将其分配给一个变量,然后 return 将状态分配给 R。然后它只是将 R 中的列表转换为数据帧。
library(reticulate)
library(stringr)
library(glue)
library(tibble)
weird <- '{47=4578.0005, 181=23456.7831, 216=7548.2367}'
weird <- str_replace_all(weird, "=", ": ")
x <- py_run_string(
glue("weird_dict = {weird}"),
convert = T
)
x$weird_dict %>%
unlist() %>%
enframe()
#> # A tibble: 3 × 2
#> name value
#> <chr> <dbl>
#> 1 47 4578.
#> 2 181 23457.
#> 3 216 7548.
由 reprex package (v2.0.1)
于 2021-10-21 创建我不认为你可以完全避免正则表达式,但通过一些小的替换它可以被 read.table()
轻松阅读。
wt <- c("{47=4578.0005, 181=23456.7831, 216=7548.2367}")
read.table(text = gsub("[{},]", "\n", wt), sep = "=")
V1 V2
1 47 4578.001
2 181 23456.783
3 216 7548.237