найти дубликат, сравнить условие, стереть одну строку - PullRequest
0 голосов
/ 14 октября 2018

Используя следующий воспроизводимый пример:

ID1<-c("a1","a4","a6","a6","a5", "a1" )
ID2<-c("b8","b99","b5","b5","b2","b8" )
Value1<-c(2,5,6,6,2,7)
Value2<- c(23,51,63,64,23,23)
Year<- c(2004,2004,2004,2004,2005,2004)
df<-data.frame(ID1,ID2,Value1,Value2,Year)

Я хочу выбрать строки, в которых ID1 и ID2 и Year имеют одинаковое значение в соответствующих столбцах.Для этих строк я хочу сравнить Value1 и Value2 в дублирующих строках, и ЕСЛИ значения не совпадают, сотрите строку с меньшим значением.

Ожидаемый результат:

  ID1 ID2 Value1 Value2 Year         new

2  a4 b99      5     51 2004 a4_b99_2004

4  a6  b5      6     64 2004  a6_b5_2004
5  a5  b2      2     23 2005  a5_b2_2005
6  a1  b8      7     23 2004  a1_b8_2004

Я попробовал следующее: Найти уникальный идентификатор для интересующих меня условий

df$new<-paste(df$ID1,df$ID2, df$Year, sep="_")

Я могу использовать уникальный идентификатор, чтобы найтистроки базы данных, содержащие дубликаты

IND<-which(duplicated(df$new) | duplicated(df$new, fromLast = TRUE))

В цикле for, если уникальный идентификатор имеет дубликат, сравните значения и удалите строки, но цикл слишком сложен, и я не могу его решить.

for (i in df$new) {

  if(sum(df$new == i)>1)
           {
  ind<-which(df$new==i)
  m= min(df$Value1[ind])
  df<-df[-which.min(df$Value1[ind]),]
  m= min(df$Value2[ind])
  df<-df[-which.min(df$Value2[ind]),]

  }
}

Ответы [ 3 ]

0 голосов
/ 15 октября 2018

Несколько разных возможностей.Используя dplyr:

df %>%
  group_by(ID1, ID2, Year) %>%
  filter(Value1 == max(Value1) & Value2 == max(Value2))

Или:

df %>%
  rowwise() %>%
  mutate(max_val = sum(Value1, Value2)) %>%
  ungroup() %>%
  group_by(ID1, ID2, Year) %>%
  filter(max_val == max(max_val)) %>%
  select(-max_val)

Используя data.table:

setDT(df)[df[, .I[Value1 == max(Value1) & Value2 == max(Value2)], by = list(ID1, ID2, Year)]$V1]

Или:

setDT(df)[, max_val := sum(Value1, Value2), by = 1:nrow(df)
   ][, filter := max_val == max(max_val), by = list(ID1, ID2, Year)
       ][filter != FALSE
         ][, -c("max_val", "filter")]

Или:

subset(setDT(df)[, max_val := sum(Value1, Value2), by = 1:nrow(df)
             ][, filter := max_val == max(max_val), by = list(ID1, ID2, Year)], filter != FALSE)[, -c("max_val", "filter")]
0 голосов
/ 15 октября 2018

Решение без загрузки библиотек:

            ID1 ID2 Value1 Value2 Year
a6.b5.2004   a6  b5      6     64 2004
a1.b8.2004   a1  b8      7     23 2004
a4.b99.2004  a4 b99      5     51 2004
a5.b2.2005   a5  b2      2     23 2005

Код

do.call(rbind, lapply(split(df, list(df$ID1, df$ID2, df$Year)),                  # make identifiers
                      function(x) {return(x[which.max(x$Value1 + x$Value2),])})) # take max of sum
0 голосов
/ 14 октября 2018

Рассмотрим aggregate, чтобы получить максимальные значения по группам, ID1 , ID2 и Год :

df_new <- aggregate(.~ID1 + ID2 + Year, df, max)
df_new

#   ID1 ID2 Year Value1 Value2
# 1  a6  b5 2004      6     64
# 2  a1  b8 2004      7     23
# 3  a4 b99 2004      5     51
# 4  a5  b2 2005      2     23
...