我有一个数据框架列,其中包含类似字典的字符串。
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, ",")
,但是未能将其存储为字典类型结构。
我觉得在将字符串转换为字典后,过滤以18
0开头的名称是可行的,但不知道如何开始。谢谢你的建议!
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
使用strsplit
和sub
/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