【问题标题】:R: Perform multiple if conditions across two data frames of different length using for loopR:使用for循环跨两个不同长度的数据帧执行多个if条件
【发布时间】:2019-08-23 13:31:13
【问题描述】:

我对 R 相当陌生,必须解决一个(对我而言)相当复杂的问题 -> 希望能得到您的帮助!

我有 2 个不同长度的数据框:

Product <- c("A1", "A2", "C1", "D1")
Posting_Date <- c("01-2016", "03-2016", "02-2016", "01-2016")

df1 <- data.frame(Product, Posting_Date)

df1
 Product Posting_Date
1      A1      01-2016
2      A2      03-2016
3      C1      02-2016
4      D1      01-2016

Product2 <- rep(c("A1", "A2", "B1", "C1", "C2", "D1"), each = 3)
Sales_Month <- rep(c("01-2016", "02-2016", "03-2016"), times = 6)
Sales <- rep(c(2300,0,2700,250,0,3700), times =3)
df2 <- data.frame(Product2, Sales_Month, Sales)

df2
 Product2 Sales_Month Sales
1        A1     01-2016  2300
2        A1     02-2016     0
3        A1     03-2016  2700
4        A2     01-2016   250
5        A2     02-2016     0
6        A2     03-2016  3700
7        B1     01-2016  2300
8        B1     02-2016     0
9        B1     03-2016  2700
10       C1     01-2016   250
11       C1     02-2016     0
12       C1     03-2016  3700
13       C2     01-2016  2300
14       C2     02-2016     0
15       C2     03-2016  2700
16       D1     01-2016   250
17       D1     02-2016     0
18       D1     03-2016  3700

如果 df1 中列出的每个产品在 df2 (df1$Posting_Month == df2$Sales_Month) 中对应月份的销售额 > 0 并且值为如果销售额为 0 或

这是我尝试过的:

for(i in 1:dim(df1) [1]) {
  if (df1$Product == df2$Product2)
    &
    if (df1$Posting_Date == df2$Sales_Month)
      &
    if (df2$Sales > 0) {
      df1$match <- 1
    } else {df1$match <- 0}
}

但它给了我几个错误信息:

Error: unexpected '&' in:
"  if (df1$Product == df2$Product2)
    &"
Error: unexpected '&' in:
"    if (df1$Posting_Date == df2$Sales_Month)
      &"
>     if (df2$Sales > 0) {
+       df1$match <- 1
+     } else {df1$match <- 0}
Warning message:
In if (df2$Sales > 0) { :
  the condition has length > 1 and only the first element will be used
> }
Error: unexpected '}' in "}"

正确的输出应该是这样的:

 Product Posting_Date match
1      A1      01-2016     1
2      A2      03-2016     1
3      C1      02-2016     0
4      D1      01-2016     1

有人可以帮我解决这个问题吗?

【问题讨论】:

  • 您好,为了帮助您,if 中的多个条件应写入同一个括号中,例如:if (df1$Product == df2$Product2 &amp; df1$Posting_Date == df2$Sales_Month &amp; df2$Sales &gt; 0) 。此外,您需要告诉您查看的是哪个元素,即df1$Product[i] 而不是df1$Product。最后你应该有第二个循环。实际上,对于df1 的每个元素,您应该遍历df2 的所有元素以找到匹配项(找到匹配项时可以使用break 停止循环)。

标签: r for-loop if-statement


【解决方案1】:

这是一种使用流行的dplyr 库的方法。

基本上你想将两个表连接在一起,然后根据销售额是否符合你的条件创建一个新变量match

library(dplyr)

df1 %>%
  left_join(df2, by = c("Product" = "Product2", "Posting_Date" = "Sales_Month")) %>%
  mutate(match = as.numeric(Sales > 0)) %>%
  select(-Sales)

  Product Posting_Date match
1      A1      01-2016     1
2      A2      03-2016     1
3      C1      02-2016     0
4      D1      01-2016     1

由于 R 处理因子和字符变量的方式,这可能会引发警告。为每个data.frame() 做这样的事情会更正它。

df1 <- data.frame(Product, Posting_Date, stringsAsFactors = FALSE)
df2 <- data.frame(Product2, Sales_Month, Sales, stringsAsFactors = FALSE)

【讨论】:

  • 复制代码给我以下警告消息:“警告消息:列Product/Product2加入不同级别的因子,强制转换为字符向量”输出显示每个值都为1列匹配的行
  • 是的,这是由于您拥有数据框的方式。它有效,您实际上可以忽略它。如果你在data.frame() 语句中执行stringsAsFactors = FALSE,那将会消失。
  • 抱歉,你还是写了这个!工作谢谢!
【解决方案2】:

为了更安全的方式,没有循环,更高效。

> tmp=aggregate(df2$Sales,list(df2$Product2,df2$Sales_Month),max)
> colnames(tmp)=c("Product","Posting_Date","match")
> tmp$match=ifelse(tmp$match>0,1,0)
> merge(df1,tmp,by=c("Product","Posting_Date"))

  Product Posting_Date match
1      A1      01-2016     1
2      A2      03-2016     1
3      C1      02-2016     0
4      D1      01-2016     1

【讨论】:

  • 在合并之前您有什么理由汇总数据吗?
  • @Morasc 求每个组合的最大值,即找出哪个组合的值 >0。如果您要在不聚合的情况下进行合并,您将进行交叉连接,从而产生更多无用的记录。
【解决方案3】:

或者使用data.table加入

library(data.table)
setDT(df1)[df2,  match := as.integer(Sales > 0), 
        on = .(Product= Product2, Posting_Date = Sales_Month)]
df1
#   Product Posting_Date match
#1:      A1      01-2016     1
#2:      A2      03-2016     1
#3:      C1      02-2016     0
#4:      D1      01-2016     1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-17
    • 1970-01-01
    • 2023-03-17
    相关资源
    最近更新 更多