Функция выборки между повторяющимися значениями в data.frame

Итак, у меня есть объект data.frame под названием «ДАННЫЕ». Этот объект содержит один столбец с именем «Точка» (DATA$Point). Поскольку в этом конкретном столбце есть дубликаты, я хотел бы создать функцию, которая выбирает только одну строку среди этих дубликатов в DATA.

Я пытался сделать это следующим образом:

sort.song<-function(DATA){

 Point<-levels(DATA$Point)
 DATA.NEW<-DATA[1:length(Point),] 

#Ideally DATA.NEW should have an empty dataframe with nrow=length(Point) and the same columns
#as in DATA. But I THINK it will work (I don't know how to do the "ideally" way)

 for(i in 1:dim(DATA)[1]){ #dim(DATA)[1] always bigger than length(Point)
  SUBDATA<-DATA[which(DATA$Point%in%Point[i]),]

#I need to sample one row of the original data set only of the duplicates of the same value.
#So if there isn't a duplicate of one particular value, move on. Otherwise sample one between
#those duplicates.

  l<-dim(SUBDATA)[1]
  if (l==1){DATA.NEW[i,]<-SUBDATA[l,]}else{lc<-sample(1:l,1)}
  DATA.NEW[i,]<-SUBDATA[lc,]
  }
 return(DATA.NEW)
}

test<-sort.song(DATA)

Но это не работает! :( Я получаю следующее сообщение об ошибке:

Error in `[<-.factor`(`*tmp*`, iseq, value = integer(0)) : 
replacement has length zero

Может глупый вопрос, но я тут как бы без вариантов (общий R новичок)

Любая помощь будет высоко оценена!!!!


person Mohr    schedule 15.04.2014    source источник
comment
Вы хотите выбрать дубликаты случайным образом, если бы не что-то подобное, это сработало бы DATA[!duplicated(DATA$Point), ]   -  person waferthin    schedule 15.04.2014
comment
Да, я хотел бы случайным образом выбирать дубликаты (включая значение, на котором основаны дубликаты). Я имею в виду, что функция Duplicated() показывает мне только повторяющиеся значения. Я хочу сделать выборку между дубликатами и значением, в котором оно дублируется. Хорошо, я могу запутаться, так как я новичок в R.   -  person Mohr    schedule 15.04.2014


Ответы (3)


Если вы хотите выбрать случайный дубликат для сохранения, а не поведение по умолчанию duplicateds, при котором сохраняется только первый, то почему бы не случайным образом перетасовать весь набор данных, чтобы выбор первого в перетасованном наборе фактически был случайной строкой из оригинала:

DATAr <- DATA[sample(1:nrow(DATA),]
DATAr <- DATAr[!duplicated(DATAr$Point),]

Если порядок ваших исходных ДАННЫХ был важен, сохраните sample(...) в переменной, используйте ее для изменения порядка ваших данных и примените обратный порядок после удаления дубликатов (или добавьте столбец DATA$ind <- 1:nrow(DATA) и отсортируйте свои данные, чтобы восстановить это впоследствии .

person Gavin Kelly    schedule 15.04.2014
comment
Кажется, это работает, но я не мог понять, почему это работает, хе-хе-хе. Первая строковая команда выбирает все строки, не пропуская ни одной строки из исходного набора данных? Я вижу, что значение по умолчанию для выборки — replace=FALSE, так что повторяющихся строк не будет, верно? Затем во второй строковой команде вы перезаписываете объект DATAr только теми строками DATAr, которые не дублируются!? Итог: с помощью этих двух строк я создаю новый data.frame со всеми исходными строками без дубликатов? - person Mohr; 15.04.2014
comment
sample(1:nrow(DATA)) создаст перестановку номеров строк. replace здесь на самом деле не то же самое, что duplicate. Если у меня 5 строк, то моя версия может выдать 5,4,3,2,1, тогда как версия replace=TRUE может выдать 1,1,5,5,5. Первый (случайно) перевернет ваши строки, и поэтому в этом случае будет сохранен окончательный дубликат; последний replace=TRUE создаст искусственные дубликаты строк 1 и 5 - очень плохие вещи, поэтому правильный вариант по умолчанию. Ваше резюме верно. - person Gavin Kelly; 15.04.2014
comment
Замечательно. Спасибо за внимательность! - person Mohr; 15.04.2014
comment
Хорошее решение. Небольшой совет: если данные значительны, выборка всех данных может быть обременительна для времени вычислений. Будет эффективнее просто перетасовать индексы и сделать выборку оттуда - person Ricardo Saporta; 15.04.2014

R имеет встроенные функции, sample и duplicated. Таким образом, вы можете просто использовать

DATA[ sample( !duplicated(DATA$Point), N ), ]
# where `N` is the sample size you'd like. 

в синтаксисе data.table вышеприведенное будет

DATA[ sample( !duplicated(Point), N )]
person Ricardo Saporta    schedule 15.04.2014
comment
Я недостаточно ясно выразился в своем вопросе. Использование !duplicated даст только те, которые не являются дубликатами, верно? Я хочу попробовать только дублированные. Я включил дополнительную информацию по исходному вопросу. - person Mohr; 15.04.2014
comment
можно убрать челку (!). Если вам нужны все такие строки, используйте sample(DATA$Point %in% DATA$Point[duplicated(DATA$Point)]) - person Ricardo Saporta; 15.04.2014

Итак, вы хотите, чтобы каждая строка, которая не дублируется, И первый экземпляр тех, которые дублируются, верно?

Тогда попробуйте это:

# build fake dataset
DATA <- as.data.frame(cbind(sample(c(1:10,3:7)),sample(1:15),sample(1:15)))
names(DATA) <- c("Point","some_col","some_other_col")

# check
print(DATA) # See Point has duplicate values


# your function
filter_data <- function(DATA){
distinct_points <- unique(DATA$Point)
as.data.frame(t(sapply(distinct_points, function(x){subset(DATA,Point == x)[1,]})))
}


#result
DATA.new <- filter_data(DATA)
print(DATA.new)
person Moody_Mudskipper    schedule 15.04.2014
comment
Не могли бы вы объяснить мне, что означает эта строковая команда? as.data.frame(t(sapply(distinct_points, function(x){subset(DATA,Point == x)[1,]}))) } - person Mohr; 15.04.2014
comment
sapply берет все отдельные точки одну за другой и берет первую строку DATA с этим значением, он возвращает матрицу, которую я должен транспонировать, чтобы вернуть ее в исходный формат, а затем преобразовать обратно в data.frame. - person Moody_Mudskipper; 15.04.2014