【发布时间】:2020-06-03 10:17:04
【问题描述】:
我有一个长格式平衡数据框 (df1),它有 7 列:
df1 <- structure(list(Product_ID = c(1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3,
3, 3, 3, 3), Product_Category = structure(c(1L, 1L, 1L, 1L, 1L,
2L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L), .Label = c("A", "B"), class = "factor"),
Manufacture_Date = c(1950, 1950, 1950, 1950, 1950, 1960,
1960, 1960, 1960, 1960, 1940, 1940, 1940, 1940, 1940), Control_Date = c(1961L,
1962L, 1963L, 1964L, 1965L, 1961L, 1962L, 1963L, 1964L, 1965L,
1961L, 1962L, 1963L, 1964L, 1965L), Country_Code = structure(c(1L,
1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L), .Label = c("ABC",
"DEF", "GHI"), class = "factor"), Var1 = c(NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), Var2 = c(NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA)), row.names = c(NA,
15L), class = "data.frame")
此数据集中的每个 Product_ID 都与唯一的 Product_Category 和 Country_Code 以及 Manufacture_Date 相关联,并且随着时间的推移 (Control_Date) 被跟踪。 Product_Category 有两个可能的值(A 或 B); Country_Code 和 Manufacture_Date 分别有 190 和 90 个唯一值。有 400,000 个唯一的 Product_ID,在 50 年期间(Control_Date 从 1961 年到 2010 年)被跟踪。这意味着 df1 有 20,000,000 行。此数据框的最后两列在开头为 NA,必须使用另一个数据框 (df2) 中可用的数据来填充:
df2 <- structure(list(Product_ID = 1:6, Product_Category = structure(c(1L,
2L, 1L, 1L, 1L, 2L), .Label = c("A", "B"), class = "factor"),
Manufacture_Date = c(1950, 1960, 1940, 1950, 1940, 2000),
Country_Code = structure(c(1L, 2L, 3L, 1L, 2L, 3L), .Label = c("ABC",
"DEF", "GHI"), class = "factor"), Year_1961 = c(5, NA, 10,
NA, 6, NA), Year_1962 = c(NA, NA, 4, 5, 3, NA), Year_1963 = c(8,
6, NA, 5, 6, NA), Year_1964 = c(NA, NA, 9, NA, 10, NA), Year_1965 = c(6,
NA, 7, 4, NA, NA)), row.names = c(NA, 6L), class = "data.frame")
第二个数据框包含关于完全相同的 400,000 种产品的另一种宽格式信息。每行代表一个唯一的产品 (Product_ID),并附有其 Product_Category、Manufacture_Date 和 Country_Code。还有 50 个其他列(从 1961 年到 2010 年的每一年),其中包含这些年份中每种产品的测量值(或 NA)。
现在我想做的是通过对第二个数据帧中可用的数据进行一些计算来填充第一个数据帧中的 Var1 和 Var2 列。更准确地说,对于第一个数据框中的每一行(即 Control_Date "t" 的产品),最后两列定义如下:
Var1:df2 中 Product_Category、Manufacture_Date 和 Country_Code 在 Year_t 中具有非 NA 值的产品总数;
Var2:df2 中 Product_Category 不同但 Manufacture_Date 和 Country_Code 在 Year_t 中具有非 NA 值的产品总数。
我最初使用嵌套 for 循环的解决方案如下:
for (i in unique(df1$Product_ID)){
Category <- unique(df1[which(df1$Product_ID==i),"Product_Category"])
Opposite_Category <- ifelse(Category=="A","B","A")
Manufacture <- unique(df1[which(df1$Product_ID==i),"Manufacture_Date"])
Country <- unique(df1[which(df1$Product_ID==i),"Country_Code"])
ID_Similar_Product <- df2[which(df2$Product_Category==Category & df2$Manufacture_Date==Manufacture & df2$Country_Code==Country),"Product_ID"]
ID_Quasi_Similar_Product <- df2[which(df2$Product_Category==Opposite_Category & df2$Manufacture_Date==Manufacture & df2$Country_Code==Country),"Product_ID"]
for (j in unique(df1$Control_Date)){
df1[which(df1$Product_ID==i & df1$Control_Date==j),"Var1"] <- length(which(!is.na(df2[which(df2$Product_ID %in% ID_Similar_Product),paste0("Year_",j)])))
df1[which(df1$Product_ID==i & df1$Control_Date==j),"Var2"] <- length(which(!is.na(df2[which(df2$Product_ID %in% ID_Quasi_Similar_Product),paste0("Year_",j)])))
}
}
这种方法的问题在于它需要很长时间才能运行。所以我想知道是否有人可以建议一个可以在更短的时间内完成这项工作的矢量化版本。
【问题讨论】:
-
嘿!请给我们您的数据的一个小样本。发布
dput(yourDataframe[1:20,])的输出。 -
感谢您的回复 Georgery 和 Wimpel。我刚刚编辑了我的问题并为其添加了一个可重现的示例。
-
嗨,索拉博!您说第二个数据框包含 400,000 条记录,其中每一行代表一个唯一的产品 (Product_ID),并附有其 Product_Category、Manufacture_Date 和 Country_Code。但是 Product_Category (2)、Manufacture_Date (90) 和 Country_Code (190) 的唯一组合数只有 34,200,而不是 400,000。你能澄清一下吗?是否有另一个变量会增加数据的大小?
-
你好@爱德华!感谢您的评论。三元组(Product_Category、Manufacture_Date、Country_Code)在第二个数据帧中不一定是唯一的。第二个数据帧的每一行唯一定义的确实是四元组(Product_ID、Product_Category、Manufacture_Date、Country_Code),即两个不同的产品(具有不同 ID)可能具有完全相同的 Product_Category、Manufacture_Date 和 Country_Code。这就是为什么行数不限于 34200 的原因。希望这能澄清!
标签: r loops vectorization data-cleaning