R - Как добавить логический столбец в кадре данных, проверяя, существует ли запись во всем кадре данных? - PullRequest
0 голосов
/ 10 апреля 2020

У меня есть такой фрейм данных:

|Type  |Date      |Material|Customer|
|Quote |01-01-2020|A       |Cust1   |
|Quote |01-02-2020|B       |Cust2   |
|Quote |05-03-2020|C       |Cust3   |
|Order |03-01-2020|A       |Cust1   |
|Order |05-04-2020|B       |Cust2   |

, и мне нужно добавить новый столбец под названием «Выигранная кавычка»: если Type = Quote и существует запись во фрейме данных, где Type = Order и Дата <(Дата цитаты + 30 дней) и Дата> = (Дата цитаты) и Materiale = Материал цитаты и Клиент = Цитировать клиента, затем «Выиграл», иначе «Потерян». Таким образом, вывод должен быть:

|Type  |Date      |Material|Customer|Won Quote|
|Quote |01-01-2020|A       |Cust1   |Won      |
|Quote |01-02-2020|B       |Cust2   |Lost     |
|Quote |05-03-2020|C       |Cust3   |Lost     |
|Order |03-01-2020|A       |Cust1   |         |
|Order |05-04-2020|B       |Cust2   |         |

Как это сделать?

Ответы [ 2 ]

1 голос
/ 10 апреля 2020

Загрузка данных:

df <- data.frame(
  Type = c("Quote", "Quote", "Quote", "Order", "Order") %>% factor(levels = c("Quote", "Order")),
  Date = c("01-01-2020", "01-02-2020", "05-03-2020", "03-01-2020", "05-04-2020") %>% 
    as.Date(format = "%d-%m-%Y"),
  Material = c("A", "B", "C", "A", "B") %>% factor(levels = c("A", "B", "C")),
  Customer = paste0("Cust", c(1, 2, 3, 1, 2)) %>% factor(levels = paste0("Cust", 1:3))
)

df

   Type       Date Material Customer
1 Quote 2020-01-01        A    Cust1
2 Quote 2020-02-01        B    Cust2
3 Quote 2020-03-05        C    Cust3
4 Order 2020-01-03        A    Cust1
5 Order 2020-04-05        B    Cust2

Сначала я хотел использовать mutate, но ваше логическое утверждение было слишком запутанным. Это for l oop безобразно, но должно работать:

df$`Won Quote` <- NA

for (i in seq_len(nrow(df))){
  if (df[i, "Type"] == "Quote" &
      any((df$Type == "Order") & 
          (df$Date < df[i, "Date"] + 30) & 
          (df$Material == df[i, "Material"]) & 
          (df$Customer == df[i, "Customer"])
         )
      ) df$`Won Quote`[i] <- "Won"
  else df$`Won Quote`[i] <- "Lost"
}

df

   Type       Date Material Customer Won Quote
1 Quote 2020-01-01        A    Cust1       Won
2 Quote 2020-02-01        B    Cust2      Lost
3 Quote 2020-03-05        C    Cust3      Lost
4 Order 2020-01-03        A    Cust1      Lost
5 Order 2020-04-05        B    Cust2      Lost
0 голосов
/ 10 апреля 2020

Мы можем создать два отдельных набора данных для "Quote" и "Order", left_join данных с помощью 'Material' и 'Customer', чтобы проверить, находятся ли даты в диапазоне, и назначить "Won" или "Lost".

library(dplyr)

df$Date <- as.Date(df$Date, '%d-%m-%Y')
df1 <- subset(df, Type == "Quote")
df2 <- subset(df, Type == "Order")


left_join(df1, df2, by = c('Material', 'Customer'))  %>%
       mutate(Won_Quote = if_else(Date.y > Date.x & Date.y < (Date.x + 30), 
                          "Won", "Lost", missing = "Lost")) %>%
       group_by(Customer, Material) %>%
       summarise(Won_Quote = if (any(Won_Quote == "Won")) "Won" else "Lost")

# Customer Material Won_Quote
#  <fct>    <fct>    <chr>    
#1 Cust1    A        Won      
#2 Cust2    B        Lost     
#3 Cust3    C        Lost     
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...