R:在data.frame中查找包含字符串的行,并在同一行中编辑其他单元格

时间:2018-09-15 19:23:32

标签: r

我有一个data.frame,其中列出了我称之为COSTOFGOOD的产品及其成本列表。

另一个data.frame具有本月的销售量,被称为SALESREPORT

我希望R逐行通过COSTOFGOOD,将列COSTOFGOOD$ProductIDSALESREPORT$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

使用ProductCOSTCOSTOFGOOD的内容,但仅当在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的事情:

  1. 第一个for loop fProductID。我使用grepProductID中找到SALESREPORT。然后,我将在rowname中找到的ROW_SALESREPORT保存起来。

  2. 我启动第二个for loop,其目的是复制相应COSTOFGOOD$ProductCOST的{​​{1}}的内容。我将其保存在ProductID

  3. 我将COST的内容添加到COST

  4. 中的相应单元格中

2 个答案:

答案 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)
)