将字符串转换为R中的词典



我有一个数据框架列,其中包含类似字典的字符串。

data = data.frame(date = c('2022-12-01', '2022-12-02'), 
code = c("{"551":4,"181":4,"180":4,"181":4}",
"{"321":14,"181":4,"230":4,"189":12}"))

我的目标是计算如果";字典";从CCD_ 1开始。

例如,第一行2022-12-01,有三个项目以18开头,因此总数为4+4+4 =12。对于第二行2022-12-02,有两个项目以18开头,因此总数为4+4+12=16

我尝试了strsplit(data$code, "\W"),它在每个分隔符上进行拆分;或者strsplit(data$code, ","),但是未能将其存储为字典类型结构。

我觉得在将字符串转换为字典后,过滤以180开头的名称是可行的,但不知道如何开始。谢谢你的建议!

data = data.frame(date = c('2022-12-01', '2022-12-02'), 
code = c("{"551":4,"181":4,"180":4,"181":4}",
"{"321":14,"181":4,"230":4,"189":12}"))
data$count <- lapply(data$code,jsonlite::fromJSON) |> sapply(
(x) sum(unlist(x)[grep("^18", names(x))]) )
data
#>         date                                code count
#> 1 2022-12-01   {"551":4,"181":4,"180":4,"181":4}    12
#> 2 2022-12-02 {"321":14,"181":4,"230":4,"189":12}    16

以下是几种方法。第一个使用CCD_ 11,并且特别短。下一个展示了如何使用strapply创建字典,最后一个只使用基本R。

在所有这些中,使用transform(data, sum = ...)或使用dplyr中的mutate将溶液作为新列添加到data中。

1)匹配18后面的数字,然后将匹配项转换为数字并求和。使用strapply可以得到特别简洁的代码。

library(gsubfn)
sapply(strapply(data$code, '"18\d+":(\d+)', as.numeric), sum)
## [1] 12 16

2)在这个问题中,首先提到了创建一本词典的可取性。为了做到这一点,下面的dict是一个字典列表,每行一个,然后我们输出所需的元素并求和。

library(gsubfn)
dict <- strapply(data$code, '"(\d+)":(\d+)', x + y ~ setNames(as.numeric(y), x))
sapply(lapply(dict, function(x) x[grepl("^18", names(x))]), sum)
## [1] 12 16
dict
## [[1]]
## 551 181 180 181 
##   4   4   4   4 
##
## [[2]]
## 321 181 230 189 
##  14   4   4  12 

3)基本解决方案将{,}和逗号字符替换为换行符,然后将每行的其余字符读入两列(字典)。然后,它将以18开头的行进行子集化并求和。

sapply(data$code, function(x) 
gsub('[{},]', 'n', x) |> 
read.table(text = _, sep = ":") |>
subset(grepl("^18", V1)) |>
with(sum(V2)), USE.NAMES = FALSE)
## [1] 12 16

如果你只想要构建字典的那部分代码

lapply(data$code, function(x) 
gsub('[{},]', 'n', x) |> 
read.table(text = _, sep = ":"))
## [[1]]
##    V1 V2
## 1 551  4
## 2 181  4
## 3 180  4
## 4 181  4
## 
## [[2]]
##    V1 V2
## 1 321 14
## 2 181  4
## 3 230  4
## 4 189 12

我首先会制作一个data.frame,其中每一行都是{name,value}对。为此,我首先将对分隔成行,然后将名称和值分隔成单独的列。然后我解析文本,只保留数字。最后,我们按日期总结该表,取名称以"开头的那些值的总和;18〃;。

library(tidyverse)
data %>% 
separate_rows(code, sep = ',') %>% 
separate(code, sep = '":', into = c('name', 'value')) %>% 
mutate(across(c(name, value), parse_number)) %>% 
group_by(date) %>% 
summarise(result = sum(value[substr(name, 1, 2) == "18"]))

使用base R

data$Sum <-  sapply(regmatches(data$code, gregexpr('(?<=18\d":)(\d+)', 
data$code, perl = TRUE)), (x) sum(as.numeric(x)))
data$Sum
[1] 12 16

使用strsplitsub/gsub基本R方法。

首先删除大括号和引号,然后查找以^18开头的字符串,最后查找sum(:之后的尾随数字)。

cbind(df, Sum = sapply(strsplit(df$code, ","), function(x) 
sum(as.numeric(
sub(".*:", "", grep("^18", gsub("\{|"|\}", "", x), value=T)))
)))
date                                code Sum
1 2022-12-01   {"551":4,"181":4,"180":4,"181":4}  12
2 2022-12-02 {"321":14,"181":4,"230":4,"189":12}  16

相关内容

  • 没有找到相关文章

最新更新