Разобрать словарную структуру, в которой ключ и значения имеют числовые значения c, используя R - PullRequest
1 голос
/ 20 апреля 2020

Я пытаюсь разобрать некоторые странные структуры данных, с которыми я столкнулся во время моих путешествий. По сути они похожи на python или javascript словари, но ключ и значение - это цифры c:

weird <- "{47=4578.0005, 181=23456.7831, 216=7548.2367}"

В надежде преобразовать это в таблицу я попытался преобразовать его в более типичный формат словаря и его синтаксический анализ с использованием 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, но я надеялся, что добрая душа может иметь некоторое представление о более элегантном / компактном решении (надеюсь, избегая регулярных выражений в целом), которое может разобрать это в таблицу как таковую:

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.

Спасибо!

Ответы [ 3 ]

3 голосов
/ 20 апреля 2020

Я не думаю, что вы можете вообще избежать регулярных выражений, но с некоторыми незначительными заменами это можно легко прочитать по 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
3 голосов
/ 20 апреля 2020

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 

Это предполагает, что все ключи и значения полностью цифра c (возможно, отрицательная, возможно, десятичная), но нет научных c обозначений в этом шаблоне. Это не невозможно включить, поэтому, если вам нужно go чуть дальше: https://www.regular-expressions.info/floatingpoint.html, Разбор научных обозначений c разумно? и Regex для цифры в научной нотации c? может помочь.

Следующим шагом может быть просто

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.

(Очевидная потеря десятичных знаков - это просто представление, необработанное данные по-прежнему имеют нецелые значения.)

2 голосов
/ 20 апреля 2020

Хотя вам может понадобиться компактная версия без регулярных выражений, мне она кажется наиболее удобной и простой в использовании:

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.

Создано в 2020-04-20 представьте пакет (v0.3.0)

Я не против сделать три прохода по данным, выполняя только одну вещь на каждом шаге. Мне гораздо легче читать и рассуждать.

...