使用条件和子类别过滤(分层)数据

时间:2019-01-07 20:30:31

标签: r filter

我需要过滤我的数据,根据某些条件以某种方式进行分层。

我的出口数据看起来像这样,但是有多个国家和年份。

df3dgt <- data.frame(
"Reporter" = c("USA", "USA", "USA", "USA", "USA", "USA","USA", "USA", "USA","USA","EU", "EU","EU","EU","EU", "EU","EU","EU","EU"),
"Partner" = c( "EU", "EU","EU","EU", "EU","EU","EU", "EU","EU","EU","USA", "USA", "USA","USA","USA", "USA", "USA","USA","USA"), 
"Commodity code" = c("1", "11", "111", "112", "12","2", "21","211", "22", "3", "1", "11", "111", "112", "2", "21", "211", "212", "22"), 
 "Value" = c( 100, 50, 25, 5, 40, 200, 170, 170, 30, 220, 190, 190, 120, 30, 300, 200, 150, 50, 100), 
 stringsAsFactors = FALSE)

商品代码汇总了不同级别的数据。例如,111(例如苹果)和112(例如香蕉)是商品11(例如水果)的子类别,类似地,11(水果)和12(蔬菜)是1(例如食物)的子类别。

我需要过滤数据以将其余的完整数据分开。

我要根据两个条件进行过滤:

(1)过滤子商品类别的“值”等于在较高聚合级别上报告的值的数据。 例如,美国出口到欧盟的商品代码1不完整。商品112(val = 5)和商品111(val = 25)不合计为商品11(val = 50)的价值。同样,值11(val = 50)和12(val = 40)不会合计为商品代码1(100)的值 相反,欧盟向美国出口的类别2已完成。商品211(val = 150)和212(val = 50)总计达到商品21(val = 200)的水平。此外,产品类别21(200)和22(100)的价值总计达到商品2的水平。

2)我还要分别过滤仅在较高级别的商品代码中报告的数据。要参考仅在较高级别上报告的数据,请考虑以下商品代码的插图清单:

 Comlist <- c("1", "11", "111", "112", "12","2", "21","211", "22","221", "3","31", "32", "311", "321")
 Comlist <- as.data.frame(Comlist)

因此,我想在美国和欧盟之间的出口中过滤商品22,因为我知道存在类别221,并且没有报告。同样,对于类别3,也不会报告其较低级别。

要处理(1),我当时正在考虑一个级别(前两个和三个数字的产品类别,然后是一个和两个)。 我首先为每个类别的产品类别创建一个新变量

# create new variable Prodcat1
df1 <- df %>%
group_by(Reporter, Partner) %>%
mutate(Prodcat1 = str_extract(Product.cat., "^.{1}")) 

# create new variable Prodcat2 for my 2nd level product category
df2 <- df1 %>%
group_by(Reporter, Partner) %>%
mutate(Prodcat2 = str_extract(Product.cat., "^.{2}"))  

然后我过滤

 df2.Incomplete <- df2 %>%
 group_by(Reporter, Partner, Prodcat2) %>%
 filter(sum(Val[2:n()]) < Val[1])`

但是,这仅包含带有两位或三位数字的商品代码的数据,而我也希望包含不完整数据的第一位数字。例如它报告的行带有“商品代码” 111和11,但不包含不完整组的商品代码“ 1”。 此外,考虑到我有一百个国家和产品类别需要考虑,我不确定要对情况(2)进行过滤。

非常感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

这仍然有点混淆您的目标。但这是一个可以提供帮助的功能:

功能

# check function
checkLowerLevels <- function (df = df3dgt, defaultValue = TRUE) {
  # set column commodity.code to integer
  class(df$Commodity.code) <- 'integer' 
  # checks
  out <- vapply(1:nrow(df), function (k, defaultValue) {
    # Checks at lower level if values add up to parent level
    # if no lower exists, default value is TRUE.
    # 
    # For a given incomplete parent return parent + children
    # separated by ';' (can be split using strsplit).
    currentCode <- .subset2(df, 3)[k]
    currentRepo <- .subset2(df, 1)[k]
    currentPart <- .subset2(df, 2)[k]
    lowerLevels <- (.subset2(df, 3) > currentCode*10-1) & (.subset2(df, 3) < (currentCode+1)*10) & (.subset2(df, 1) == currentRepo) & (.subset2(df, 2) == currentPart)
    check <- ifelse(!any(lowerLevels), defaultValue, sum(.subset2(df, 4L)[lowerLevels]) == .subset2(df, 4L)[k])
    res <- NA_character_
    if (check) return (c(res,check))
    res <- paste(currentCode, paste(.subset2(df, 3L)[lowerLevels], collapse = ';'), sep = ';')
    return(c(res,check)) 
  }, character(2), defaultValue = defaultValue)
  out <- t(out)
  ans <- data.frame(check=out[,2], subset=out[,1], stringsAsFactors = FALSE)
  class(ans$check) <- 'logical'
  ans
}

结果

这是一个应用程序:

# create new columns in data frame
df3dgt <- cbind(df3dgt, checkLowerLevels())
df3dgt 
#    Reporter Partner Commodity.code Value check     subset
# 1       USA      EU              1   100 FALSE    1;11;12
# 2       USA      EU             11    50 FALSE 11;111;112
# 3       USA      EU            111    25  TRUE       <NA>
# 4       USA      EU            112     5  TRUE       <NA>
# 5       USA      EU             12    40  TRUE       <NA>
# 6       USA      EU              2   200  TRUE       <NA>
# 7       USA      EU             21   170  TRUE       <NA>
# 8       USA      EU            211   170  TRUE       <NA>
# 9       USA      EU             22    30  TRUE       <NA>
# 10      USA      EU              3   220  TRUE       <NA>
# 11       EU     USA              1   190  TRUE       <NA>
# 12       EU     USA             11   190 FALSE 11;111;112
# 13       EU     USA            111   120  TRUE       <NA>
# 14       EU     USA            112    30  TRUE       <NA>
# 15       EU     USA              2   300  TRUE       <NA>
# 16       EU     USA             21   200  TRUE       <NA>
# 17       EU     USA            211   150  TRUE       <NA>
# 18       EU     USA            212    50  TRUE       <NA>
# 19       EU     USA             22   100  TRUE       <NA>

说明

  • 函数checkLowerLevels检查由报告人和合作伙伴过滤的任何代码n的完整性(这样,n = 1USA -> EU处理一次,'EU-> USA被处理一次) ')
  • 要这样做,它会自动将其低一级,并将汇总的低值与较高的值进行比较
  • 如果代码不完整,它还会以n格式返回代码n1, n2, ..., nm和子级n;n1;n2;...;nm