Удаление дубликатов с условием - PullRequest
0 голосов
/ 16 февраля 2019

Мне нужно удалить дубликаты строк.Обе строки и с условием.Ниже приведен пример фрейма данных.

Sr. Invoice Status    Name
1   XXX     Booked    ABC
2   YYY     Booked    DEF
3   YYY     Cancelled DEF
4   ZZZ     Booked    GHI
5   ZZZ     Changed   GHI

Мне нужно удалить оба экземпляра счетов, которые были повторены, и статус отменен.

Вот как должен выглядеть фрейм данных:

Sr. Invoice Status    Name
1   XXX     Booked    ABC
2   ZZZ     Booked    GHI
3   ZZZ     Changed   GHI

И мне нужно отделить фрейм данных для удаленного набора.То есть:

Sr. Invoice Status    Name
1   YYY     Booked    DEF
2   YYY     Cancelled DEF

Ответы [ 4 ]

0 голосов
/ 16 февраля 2019

Я думаю, что есть более простой способ использования tidyverse.Создайте группы, а затем filter на уровне группы, используя базу all и any.

library(tidyverse) # Load library

Чтобы удалить группы с отмененным статусом:

df %>%
  group_by(Invoice) %>% 
  filter(all(Status != "Cancelled"))

# A tibble: 3 x 4
# Groups:   Invoice [2]
    Sr. Invoice Status  Name 
  <dbl> <chr>   <chr>   <chr>
1     1 XXX     Booked  ABC  
2     4 ZZZ     Booked  GHI  
3     5 ZZZ     Changed GHI

Для разделения группс отмененным статусом:

df %>%
  group_by(Invoice) %>% 
  filter(any(Status == "Cancelled"))

# A tibble: 2 x 4
# Groups:   Invoice [1]
    Sr. Invoice Status    Name 
  <dbl> <chr>   <chr>     <chr>
1     2 YYY     Booked    DEF  
2     3 YYY     Cancelled DEF  
0 голосов
/ 16 февраля 2019

Вы также можете сделать:

library(dplyr)

df %>%
  group_by(Invoice) %>%
  mutate(Cancellation = +(any(Status == 'Cancelled'))) %>%
  split(., .$Cancellation) %>%
  setNames(., c("NoCancellations", "Cancellations")) %>%
  list2env(., .GlobalEnv)

Это приведет к созданию в вашей среде 2 новых фреймов данных с именами NoCancellations и Cancellations (вы можете переименовать их по своему желанию).

NoCancellations

# A tibble: 3 x 5
# Groups:   Invoice [2]
     Sr Invoice Status  Name  Cancellation
  <int> <chr>   <chr>   <chr>        <int>
1     1 XXX     Book    AB               0
2     4 ZZZ     Book    GH               0
3     5 ZZZ     Changed GH               0

Cancellations

# A tibble: 2 x 5
# Groups:   Invoice [1]
     Sr Invoice Status    Name  Cancellation
  <int> <chr>   <chr>     <chr>        <int>
1     2 YYY     Book      DE               1
2     3 YYY     Cancelled DE               1

Новые фреймы данных также будут содержать столбец с именем Cancellation, который использовался для разделения;Вы можете удалить это, если необходимо, например:

df %>%
  group_by(Invoice) %>%
  mutate(Cancellation = +(any(Status == 'Cancelled'))) %>%
  split(., .$Cancellation) %>%
  lapply(., function(x) { x["Cancellation"] <- NULL; x }) %>%
  setNames(., c("NoCancellations", "Cancellations")) %>%
  list2env(., .GlobalEnv)

Вместо lapply, вы также можете использовать purrr::map(., ~ (.x %>% select(-Cancellation))) в этой строке.

0 голосов
/ 16 февраля 2019

Используя ave мы строим логический вектор, а split мы используем его для создания 2 отдельных фреймов данных:

split(df1,ave(df1$Status, df1$Invoice, FUN = function(x) tail(x,1) != "Cancelled"))

# $`FALSE`
#   Sr. Invoice    Status Name
# 2   2     YYY    Booked  DEF
# 3   3     YYY Cancelled  DEF
# 
# $`TRUE`
#   Sr. Invoice  Status Name
# 1   1     XXX  Booked  ABC
# 4   4     ZZZ  Booked  GHI
# 5   5     ZZZ Changed  GHI

Ответ был дан с учетом комментария к вопросу, что заставляет меня задуматьсярелевантным является только появление Cancelled в качестве последнего элемента.

data

df1 <- read.table(header=TRUE,stringsAsFactors=FALSE,text="Sr. Invoice Status    Name
1   XXX     Booked    ABC
2   YYY     Booked    DEF
3   YYY     Cancelled DEF
4   ZZZ     Booked    GHI
5   ZZZ     Changed   GHI")
0 голосов
/ 16 февраля 2019

Учитывая набор данных, подобный этому:

> d
  Sr Invoice    Status Name
1  1     XXX      Book   AB
2  2     YYY      Book   DE
3  3     YYY Cancelled   DE
4  4     ZZZ      Book   GH
5  5     ZZZ   Changed   GH

Это выражение находит все коды счетов для всего, что имеет статус Отменено:

> d$Invoice[d$Status=="Cancelled"]
[1] "YYY"

, а затем это выражение возвращает true илиfalse для всех строк с этими кодами или без них:

> d$Invoice %in% d$Invoice[d$Status=="Cancelled"]
[1] FALSE  TRUE  TRUE FALSE FALSE

Затем вы можете использовать этот логический вектор для разделения вашего фрейма данных.Например, используя split, чтобы получить список из двух элементов:

> split(d, d$Invoice %in% d$Invoice[d$Status=="Cancelled"])
$`FALSE`
  Sr Invoice  Status Name
1  1     XXX    Book   AB
4  4     ZZZ    Book   GH
5  5     ZZZ Changed   GH

$`TRUE`
  Sr Invoice    Status Name
2  2     YYY      Book   DE
3  3     YYY Cancelled   DE
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...