2016-07-11 3 views
0

Я пытаюсь получить образец из большого набора данных из трех столбцов. Образец должен соответствовать следующим критериям:Образец строки с ограниченными комбинациями

  • Получить определенное количество строк каждого значения группы. Существует три групповых значения (1,2-3,4-5)
  • Используйте только определенное количество символов в строках letter1 и letter2. То есть: Условие относительно ограниченное количество писем проверяется следующим образом: (где s является dataframe раствор)

    NROW(unique(append(s$letter1,s$letter2))) 4

Минимальный набор данных выглядит следующим образом:

>df 
letter1 letter2 value 
a  b  1 
a  c  1 
a  d  3 
b  a  1 
c  b  1 
c  d  2 
c  e  4 
d  a  5 
d  e  1 
d  c  2 

(Значение в lettter1 всегда отличается от значения в letter2).

Например, из примера набора данных я хочу образец, который включает в себя 1 строку значения 4-5, 1 строку значения 2-3 и 4 строки значения 1. Я хочу, чтобы на панели отображались только комбинации из 4 разных букв первые две колонки. В этом случае есть два возможных решения (и их перестановки), как с использованием букв a, b, c, d. Мне просто нужно получить одну (или перестановку), мне все равно.

>s1 
letter1 letter2 value  
a  b  1 
a  c  1 
a  d  3 
b  a  1 
c  b  1 
d  a  5 

>s2 
letter1 letter2 value 
a  b  1 
a  c  1 
b  a  1 
c  b  1 
c  d  2 
d  a  5  

Раствор для минимальной dataframe но не реально (больше) один

Я решил эту проблему для минимальной dataframe выше, но, к сожалению, слишком медленно для реального dataframe мне нужно обработать. Эти решения состоят из:

  • Получение возможной комбинации желаемого количества уникальных букв (u = 4 в этом примере).
  • Для каждой из этих комбинаций перестановки в наборах из двух (как они могут появляться в столбцах letter1 и letter2 в кадре данных).
  • Получите строки в фрейме данных перестановок (l), которые также находятся в исходном (df), используя semi_join().
  • Получите строки, принадлежащие каждой группе значений, и проверьте, достаточно ли их для удовлетворения требуемого количества строк для каждой группы.
  • Если это так, и если для удовлетворения этого требования требуется больше, выберите произвольно между ними.

Функция ниже возвращает первую группу букв u, с комбинацией которых мы можем встретить требуемое количество строк в каждой группе, заданной группами. группы - это числовой вектор трех разрезов, которые представляют количество строк для каждой группы значений. группы [1] - количество требуемых строк со значением 1, группы [2] число требуемых строк со значениями 2-3 и группы [3] число требуемых строк со значениями 4-5.

library(trotter) 
library(gtools) 
library(dplyr) 

obtainValues <- function (df,u,groups){ 

# Get unique letter values in the dataframe 
lett <- unique(append(df$letter1,df$letter2)) 

# All possible combinations of letters in lett in groups of u letters 
letters <- cpv(u,lett) 

# Iterate over any possible group of 4 letters 
for(i in 1:length(letters)){ 

    l <- as.character(letters[i]) 
    l <- as.data.frame(permutations(u,2,l),stringAsFactors=FALSE) 
    names(l) <- c("letter1","letter2") 

    dc <- semi_join(df,l,by = c("letter1", "letter2")) 


    #Groups of values of each type with the current letters 
    g1 <- dc[dc$value == 1,] 
    g2 <- dc[dc$value > 1 & dc$value < 4,] 
    g3 <- dc[dc$value > 3,] 

    if(NROW(g1) >= groups[1] & NROW(g2) >= groups[2] & NROW(g3) >= groups[2]){ 

     # I do not want more rows of each type than the requested ones 
     g1 <- g1[sample(nrow(g1),groups[1]),] 
     g2 <- g2[sample(nrow(g2),groups[2]),] 
     g3 <- g3[sample(nrow(g3),groups[3]),] 

     # Join chosen rows in a dataframe 
     g <- rbind(g1,g2) 
     g <- rbind(g,g3) 
     return(g) 
    } 
} 
} 


df <- data.frame(c("a","a","a","b","c","c","c","d","d","d"),c("b","c","d","a","b","d","e","a","e","c"), c(1,1,3,1,1,2,4,5,1,2), stringsAsFactors=FALSE) 
names(df) <- c("letter1","letter2","value") 

groups <- c(4,1,1) 
u <- 4 
obtainValues(df,u,tieGroups) 

Проблема

Реальный dataframe слишком велик, и это не представляется возможным перебирать 1: длина (буквы).Можно разделить длину и сделать цикл for для разных групп значений в буквах за раз, но это очень медленно, так как мой dataframe довольно большой. Есть ли другое решение? Любой способ избежать цикла for? Или способ каким-то образом адаптировать мое решение к более крупным данным?

+0

Могут быть только две возможности относительно группы значений 1 (я возьму ваше слово для этого), но есть 3 со значениями 2 и 2 со значением 3, поэтому есть (по крайней мере) 12 возможных результатов. –

+0

@ 42- Извините, но я не понимаю. Используя только комбинации из 4 разных букв в первых двух столбцах, я не вижу более двух решений. –

ответ

0

Я бы сначала сделать рандомизации строк заказов, то первый split на колонке значений (так как вы знаете размер розыгрышей в пределах этой группировки), а затем выбрать первые 4 пункта условного на !duplicated(paste(letter1, letter2, sep="_"))

rdf1 <- df1[ sample(nrow(df1)) , ] 
vspl <- with(rdf1, split(rdf1, findInterval(0,1.5,3.5, 5.5)) ) 
#-------- 
> vspl 
$`1` 
    letter1 letter2 value 
3  a  d  3 
6  c  d  2 
7  c  e  4 
5  c  b  1 
2  a  c  1 
1  a  b  1 
10  d  c  2 
4  b  a  1 
8  d  a  5 
9  d  e  1 
#-------- 
vspl <- with(rdf1, split(rdf1, findInterval(rdf1$value, c(0,1.5,3.5, 5.5)))) 
do.call(rbind, 
    lapply(names(vspl), # names rather than values to later determine number of rows 
    function(x) vspl[[x]][ # work on the nth item in the list 
     !duplicated(paste(vspl[[ x]]$letter1,vspl[[x]]$letter2,sep="_")), ][ # drop dupes 
      1:(if (x=="1") 4 else 1), ,drop=FALSE]) ) # select correct number 
    letter1 letter2 value 
5  c  b  1 
2  a  c  1 
1  a  b  1 
4  b  a  1 
3  a  d  3 
7  c  e  4 
+0

Прошу прощения за то, что в моем вопросе не было достаточно ясно, что в первых двух столбцах нужно использовать только комбинации из четырех разных букв. Ваше решение не соответствует этому требованию, поскольку предоставленный фреймворк включает в себя 5 разных букв (a, b, c, d, e). Я обновил свой ответ, надеюсь, теперь это станет более ясным. –

Смежные вопросы