2016-04-12 2 views
0

Я хотел бы подмножить свой data.frame так, чтобы он возвращал строки, которые имеют не менее 50% своих значений <= значений в определенной строке в data.frame.Как подмножить data.frame по строке в том же data.frame в R?

df

Name A B C D 
r1  2 2 2 2 
r2  4 3 1 3 
r3  1 1 1 2 
r4  3 3 3 1 

Конкретная строка Я пытаюсь Подмножество на это строка r1. Я хочу только вернуть строку r3, поскольку с 75% значений это <= до значений в строке r1.

df

Name A B C D 
r3  1 1 1 2 

Любая помощь будет оценена. Пожалуйста, дайте мне знать, нужна ли дополнительная информация.

+0

Требуется ли для сравнения сравнение только на основе r1? –

+0

@KunalPuri Спасибо за ваш вопрос. Да, на данный момент это мое намерение сделать сравнение исключительно на основе 'r1'. – Dre

+0

Кроме того, в начале вопроса вы написали: «Он возвращает строки, которые имеют не менее 50%», и, как только один читает вопрос, для строки r1 вы рассматриваете только r3, а не r2 и r4, хотя они удовлетворяют условию 50%. Не могли бы вы прояснить эту вещь? –

ответ

0

Вот общее решение, которое также может быть применено для 34 переменных:

Предположения: В наборе данных, мы сравниваем каждый столбец, за исключением первого столбца, который хранит Name.

> col_names <- colnames(df)[-1] 

> index <- which(df$Name == 'r1') 
> values <- seq(1:nrow(df))[-index] 

> row_num <- integer(0) 
> for (i in values){ 
+ min_val <- length(col_names)/2 
+ if (length(which(df[i,col_names] <= df[index,col_names])) >= min_val) 
+ row_num <- c(row_num,i) 
+ } 

> df[row_num,] 
    Name A B C D 
3 r3 1 1 1 2 

Хотя, если набор данных велик, это может занять некоторое время. Вы можете улучшить производительность с помощью пакета data.table.

+0

Благодарим вас за ответ и ваше терпение. Мне интересно, возможно ли это с вашим подходом без выполнения инструкции 'if' для каждого столбца? У меня 34 переменных в моем фактическом файле data.frame, поэтому 'if' для каждого из них не является идеальным, но он действительно работает. – Dre

2

Сложите число условий встретились строка за строкой основе с использованием «+» и сравните 3:

subset(df, ((A <= A[1]) + (B <= B[1]) + (C <= C[1]) + (D <= D[1])) >= 3) 

> subset(df, ((A <= A[1]) + (B <= B[1]) + (C <= C[1]) + (D <= D[1])) >= 3) 
    Name A B C D 
1 r1 2 2 2 2 
3 r3 1 1 1 2 

Если вы также хотите удалить «г1», а затем просто добавить [-1, ]

Это можно обобщить, чтобы предоставить числовой вектор, который можно протестировать против процентного критерия; он дает количество элементов в каждой строке, которые меньше, чем их аналоги в первой строке. Мне нужно unlist первую строку, так как, используя третий аргумент в один ряд dataframe не удалось:

rowSums(sweep(df[-1], 2, unlist(df[1,-1]), "<=")) 
[1] 4 2 4 2 

Ниже демонстрация:

df2 <- cbind(nms = paste0("r", 1:10), 
      as.data.frame(matrix(sample(1:10, 200,repl=TRUE), 10))) 
df2 
#-------------- 
nms V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14 V15 V16 V17 V18 V19 V20 
1 r1 8 6 10 7 3 7 2 8 4 9 9 4 5 4 8 7 2 1 6 4 
2 r2 3 9 6 3 9 10 6 10 10 3 3 2 4 4 4 10 3 5 2 1 
3 r3 1 7 6 8 3 5 2 3 1 5 5 4 8 3 1 6 2 10 3 7 
4 r4 2 6 10 10 8 7 9 1 4 5 6 7 2 6 8 3 5 10 10 3 
5 r5 5 5 7 2 5 10 2 9 2 9 4 6 1 5 8 5 8 6 3 5 
6 r6 4 1 7 7 6 9 6 3 4 3 2 9 4 8 10 3 4 4 10 4 
7 r7 7 1 10 4 1 2 8 5 8 8 5 5 5 6 4 10 6 9 10 6 
8 r8 10 8 1 4 1 4 10 3 1 3 10 3 4 9 4 7 4 9 2 2 
9 r9 3 10 9 1 10 8 8 4 7 2 7 2 9 10 3 3 7 4 10 1 
10 r10 4 7 3 3 1 9 4 1 9 5 3 9 9 3 9 2 9 10 2 4 
#----------------- 
rowSums(sweep(df2[-1], 2, unlist(df2[1,-1]), "<=")) 
# [1] 20 11 15 12 12 11 11 13 10 11 
rowSums(sweep(df2[-1], 2, unlist(df2[1,-1]), "<=")) >= 20*0.75 
# [1] TRUE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 

df2[ rowSums(sweep(df2[-1], 2, unlist(df2[1,-1]), "<=")) >= 20*0.75 , ] 
#--------- 
    nms V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14 V15 V16 V17 V18 V19 V20 
1 r1 8 6 10 7 3 7 2 8 4 9 9 4 5 4 8 7 2 1 6 4 
3 r3 1 7 6 8 3 5 2 3 1 5 5 4 8 3 1 6 2 10 3 7 

Это произошло со мной, что apply решение, вероятно, казалось, более очевидным для некоторых R программистов:

colSums(apply(df2[-1], 1, "<=", df2[1,-1])) >= ncol(df2)*.7 

Обратите внимание на необходимость использования colSums из-за способа, что `применить возвращает матрицу в стиле столбцов, иногда головоломка для начала.

+0

Аналогичная логика с использованием сравнения двух равных размеров кусков 'df' -' которые (rowSums (df [-1] <= df [rep (1, nrow (df)), - 1])> = (0.75 * ncol (df ​​[-1]))) ' – thelatemail

+0

@thelatemail Спасибо за ваш подход, он отлично работал. – Dre

+0

@ 42- Спасибо за ваш ответ. Можно ли использовать подмножество, не добавляя каждый столбец отдельно? Я не хочу добавлять каждый столбец, так как в моем фактическом data.frame есть 34 переменных. – Dre