我需要过滤我的数据,根据某些条件以某种方式进行分层。
我的出口数据看起来像这样,但是有多个国家和年份。
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)进行过滤。
非常感谢您的帮助。
答案 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 = 1
被USA -> EU
处理一次,'EU-> USA被处理一次) ')n
格式返回代码n1, n2, ..., nm
和子级n;n1;n2;...;nm