簡體   English   中英

在 R 中檢查總和

[英]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"])

它是如何工作的?

  1. 您會發現 Area 不以 0 結尾的行。 sodf[,grepl('0$',sodf$Area),"Area"] # "051043" "051053"
  2. 如果他們有一個 0,你會發現這一行應該如何結束。我使用了來自 stringr package 的 function。 stringr::str_replace_all(sodf[,grepl('0$',sodf$Area),"Area"],'[1-9]$','0') # "051040" "051050"
  3. 您會找到未包含在第 2 組中且不具有 '050000' 結構(^[0]+[1-9]{1}[0]+$)的行,然后將它們的總數相加。 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM