[英]Checking sums with condition in R
我需要检查一些 dataframe 中的总和。 但它的元素不能总结,因为其中一些包含其他元素。 在这个例子中,051040 是 051043 的一部分。虽然大多数元素以“0”结尾,但最后一位为 3 的元素总是大于或等于最后一位为 0 的对应元素。换句话说,我需要找到所有以“3”结尾的元素并跳过那些带有“0”的对应物。 在此示例中,必须跳过 051040 和 051050,因为存在 051043 和 051053。 注意元素“05000”是一个控制和,显然它也必须被跳过。 所以我需要找出差异:05000 - SUM ("051010", "051043", "051053", "052020", "052100", "052220", "052310") = 0 类似的东西。 这是一个人工的例子(实际的dataframe真的很大)。
Area <- c("050000", "051010", "051040", "051043", "051050", "051053", "052020", "052100", "052220", "052310")
Total <- c(100, 28, 16, 22, 10, 10, 10, 10, 10, 10)
sodf <- data.frame(Area, Total)
首先十分感谢!
您可以使用子字符串。
sodf[with(sodf, ave(substring(Area, 6) == 3, substr(Area, 1, 5), FUN=\(x) {
if (any(x)) x else TRUE
})), ] |>
(\(x) x[1, 2] - sum(x[-1, 2]))()
# [1] 0
在多个区域的应用程序中,我稍微sodf
lapply
进行演示(但不完全确定您的区号看起来如何,但前两位数字似乎相关)。
lapply(split(sodf, substr(sodf$Area, 1, 2)), \(x) {
x <- x[ave(substring(Area, 6) == 3, substr(Area, 1, 5), FUN=\(x) {
if (any(x)) x else TRUE
}), ]
x[1, 2] - sum(x[-1, 2])
})
# $`05`
# [1] 0
#
# $`06`
# [1] 111
数据:
sodf <- structure(list(Area = c("050000", "051010", "051040", "051043",
"051050", "051053", "052020", "052100", "052220", "052310", "060000",
"061010", "061040", "061043", "061050", "061053", "062020", "062100",
"062220", "062310"), Total = c(100, 28, 16, 22, 10, 10, 10, 10,
10, 10, 211, 28, 16, 22, 10, 10, 10, 10, 10, 10)), row.names = c(NA,
-20L), class = "data.frame")
一行解决方案可以是这样的:
sum(sodf[!sodf$Area %in% stringr::str_replace_all(sodf[!grepl('0$',sodf$Area),"Area"],'[1-9]$','0') & !sodf$Area %in% sodf[grepl('^[0]+[1-9]{1}[0]+$',sodf$Area),"Area"] ,"Total"])
它是如何工作的?
sodf[,grepl('0$',sodf$Area),"Area"]
# "051043" "051053"stringr::str_replace_all(sodf[,grepl('0$',sodf$Area),"Area"],'[1-9]$','0')
# "051040" "051050"sum(sodf[:sodf$Area %in% stringr:,str_replace_all(sodf[,grepl('0$',sodf$Area),"Area"],'[1-9]$','0') &,sodf$Area %in% sodf[grepl('^[0]+[1-9]{1}[0]+$',sodf$Area),"Area"] ,"Total"] )
# 100使用 dplyr package 将代码拆分为多行可以实现相同的结果。
我的同事建议了以下变体。
library(tidyverse)
check_diff <- function(df) {
# Find value Total, for instance ends with 0000
sum_control <- df |>
filter(str_detect(Area, "0{4}$")) |>
select(Total)
# Find second number from the end where the last character is 3 and connect them into one string
before_last_3 <- df |>
filter(str_detect(Area, "3$")) |>
pull(Area) |>
str_sub(-2, -2) |>
str_flatten()
# Create string for filter pattern
filter3 <- str_c("[", before_last_3, "]0$")
# filter data on new conditions and find sum
sum <- df |>
filter(!str_detect(Area, "0{4}$"),
!str_detect(Area, filter3)) |>
summarise(sum(Total))
sum_control - sum
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.