我有一个data.frame,其中列出了我称之为COSTOFGOOD
的产品及其成本列表。
另一个data.frame具有本月的销售量,被称为SALESREPORT
。
我希望R逐行通过COSTOFGOOD
,将列COSTOFGOOD$ProductID
与SALESREPORT$ProductID
进行比较,如果也找到它,则将COSTOFGOOD$ProductCOST
中的内容添加到SALESREPORT$ProductCOST
中的同一行。
这里有2个示例数据框
ProductID <- c('AA','BB','CC','DD','EE')
ProductNAME <- c('Dress1', 'Dress2', 'Dress3','Dress4','Dress5')
ProductPRICE <- c('22', '15', '16', '18', '19')
ProductCOST <- c(' ', ' ', ' ',' ', ' ')
ProductPROFIT <- c('21', '13', '13', '14', '14')
SALESREPORT <- data.frame(ProductID, ProductNAME, ProductPRICE, ProductCOST, ProductPROFIT)
ProductID <- c('DD','BB','CC','AA','GG','JJ')
ProductNAME <- c('Dress4', 'Dress2', 'Dress3','Dress1', 'Dress34','Dress15')
ProductPRICE <- c('22', '15', '16', '18', '20','54')
ProductCOST <- c('1', '2', '3', '4','5', '6')
ProductPROFIT <- c('21', '13', '13', '14','7','9')
COSTOFGOOD<- data.frame(ProductID, ProductNAME, ProductPRICE, ProductCOST, ProductPROFIT)
#Turning the first column into rownames as I need that for the code I wrote so far
rownames(COSTOFGOOD)<-COSTOFGOOD[[1]]
结果应填充ProductCOST
中的空白列SALESREPORT
ProductID ProductNAME ProductPRICE ProductCOST ProductPROFIT
1 AA Dress1 22 21
2 BB Dress2 15 13
3 CC Dress3 16 13
4 DD Dress4 18 14
5 EE Dress5 19 14
使用ProductCOST
中COSTOFGOOD
的内容,但仅当在ProductID
中找到SALESREPORT
时。
ProductID ProductNAME ProductPRICE ProductCOST ProductPROFIT
DD DD Dress4 22 1 21
BB BB Dress2 15 2 13
CC CC Dress3 16 3 13
AA AA Dress1 18 4 14
GG GG Dress34 20 5 7
JJ JJ Dress15 54 6 9
这是我到目前为止编写的代码,虽然返回了错误:
for (f in rownames(COSTOFGOOD)) {
ROW_SALESREPORT <- rownames(SALESREPORT[grep(f, SALESREPORT$ProductID),])
for(i in seq_len(nrow(COSTOFGOOD))) {
COST <- COSTOFGOOD$ProductCOST[i]
SALESREPORT$ProductCOST[ROW_SALESREPORT] <- COST
}
}
它给了我这个错误:
Error in `$<-.data.frame`(`*tmp*`, "ProductCOST", value = c(1L, 1L, 1L, :
replacement has 6 rows, data has 5
In addition: Warning message:
In `[<-.factor`(`*tmp*`, ROW_SALESREPORT, value = 6L) :
invalid factor level, NA generated
下面是我在写这篇文章时的想法的分解。可能有很多更简单的方法,但是我似乎找不到在bash中结合grep和sed来完成R的事情:
第一个for loop
f
是ProductID
。我使用grep
在ProductID
中找到SALESREPORT
。然后,我将在rowname
中找到的ROW_SALESREPORT
保存起来。
我启动第二个for loop
,其目的是复制相应COSTOFGOOD$ProductCOST
的{{1}}的内容。我将其保存在ProductID
我将COST
的内容添加到COST
答案 0 :(得分:0)
首先,让我将您的第3列到第5列强制转换为"numeric"
类。
COSTOFGOOD[3:5] <- lapply(COSTOFGOOD[3:5], function(f) as.numeric(levels(f))[f])
SALESREPORT[3:5] <- lapply(SALESREPORT[3:5], function(f) as.numeric(levels(f))[f])
现在是问题所在。
您可以将两个数据框的行与merge
匹配,然后使用rowSums
添加值。最后,将结果分配给原始的SALESREPORT
列。
mrg <- merge(SALESREPORT[c(1, 4)], COSTOFGOOD[c(1, 4)], by = "ProductID")
Sum <- rowSums(mrg[-1], na.rm = TRUE)
i <- match(mrg[["ProductID"]], SALESREPORT[["ProductID"]])
SALESREPORT[["ProductCOST"]][i] <- Sum[i]
rm(mrg, Sum, i) # tidy up
答案 1 :(得分:0)
这也可以通过加入dplyr
中的联接来完成。
我在这里假设ProductID
是连接两个表的足够的键。我从ProductCOST
中删除了空的SALESREPORT
,然后将所有这些行连接到COSTOFGOOD中匹配的行,仅引入了ProductID和ProductCOST列。
SALESREPORT %>%
select(-ProductCOST) %>%
left_join(COSTOFGOOD %>% select(ProductID, ProductCOST),
by = "ProductID")
ProductID ProductNAME ProductPRICE ProductPROFIT ProductCOST
1 AA Dress1 22 21 4
2 BB Dress2 15 13 2
3 CC Dress3 16 13 3
4 DD Dress4 18 14 1
5 EE Dress5 19 14 NA
样本数据
SALESREPORT <- data.frame(
stringsAsFactors = FALSE,
ProductID = c("AA", "BB", "CC", "DD", "EE"),
ProductNAME = c("Dress1", "Dress2", "Dress3", "Dress4", "Dress5"),
ProductPRICE = c(22L, 15L, 16L, 18L, 19L),
ProductCOST = c(NA, NA, NA, NA, NA),
ProductPROFIT = c(21L, 13L, 13L, 14L, 14L)
)
COSTOFGOOD <- data.frame(
stringsAsFactors = FALSE,
ProductID = c("DD", "BB", "CC", "AA", "GG", "JJ"),
ProductNAME = c(
"Dress4", "Dress2", "Dress3", "Dress1", "Dress34",
"Dress15"
),
ProductPRICE = c(22L, 15L, 16L, 18L, 20L, 54L),
ProductCOST = c(1L, 2L, 3L, 4L, 5L, 6L),
ProductPROFIT = c(21L, 13L, 13L, 14L, 7L, 9L)
)