2017-01-05 2 views
1

Я чувствую, что это должно быть что-то очевидное, но я весь день пытался разобраться и найти ответы, поэтому я размещаю его здесь, надеясь, что кто-то какой-либо ввод.Странное поведение возвращаемого значения при использовании apply() для подмножества матрицы

Короткий вариант заключается в том, что с помощью apply() для подмножества кадра данных значениями в другом кадре данных и возвратом среднего значения функция возвращает NA для первых 9 итераций, если количество входных строк больше 9. Если количество входных строк меньше 9, оно возвращает данные только штрафа. Для меня не очевидно, что я сделал для этого.

У меня есть два кадра данных. Первая - это данные, взятые последовательно из многочисленных выборок. фактор-уровень столбца «ID» представляют образец. Внутри каждого фактора столбец «Длина» соответствует тому, где измерение было проведено в строке по образцу. Для двух разных измерений имеются два столбца данных. Ниже приведен упрощенный, повторяемые, представление о том, что это выглядит так:

set.seed(10) 
ID=factor(sort(rep(paste(letters[1:10]), times=10))) 
Length=seq(1:10) + runif(10, 0, 0.9) 
Values_1=c(1:20) 
Values_2=c(21:40) 
test_data=cbind.data.frame(ID, Length, Values_1, Values_2) 

Следующая У меня есть матрица значений обрезания, которые я хочу использовать для подмножества в столбце «Длина» в «test_data». Каждая строка показывает, какой образец я хочу подмножить, и начальную и конечную точки подмножества.

ID2=sort(rep(paste(letters[1:10]), times=2)) 
Start=c(1, 5, 1, 5) 
Stop=c(5, 10, 7, 10) 
Row=c(1:20) 
cutoffs=cbind.data.frame(ID2, Start, Stop, Row) 
colnames(cutoffs)=c("ID", "Start", "Stop", "Row") 
#I'm recycling the cutoffs here. In reality the cutoffs are all pretty different 

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

r=9 
subset1=test_data$Values_1[test_data[,1] == cutoffs[r,1] & 
          test_data[,2] >= cutoffs[r,2] & 
          test_data[,2] <= cutoffs[r,3] & 
          !is.na(test_data[,3])] 
#[1] 1 2 3 4 
mean(subset1) 
#There are no NA's in this test data, but the !is.na is there to catch NA's that exist in the real data 

но когда я строю применить функцию к подмножеству всех вещей данных что-то странное, и я не знаю, почему , Если я запустил функцию, она возвращает только значения для отсечек [10:20,], а первые 9 образцов - NA. Но выполнение любого подмножества отсечений между строками 1 и 9 возвращает правильные значения.

apply(cutoffs, 1, function(x){ 
    subset_1=test_data$Values_1[test_data[,1] == cutoffs[x[4],1] & 
           test_data[,2] >= cutoffs[x[4],2] & 
           test_data[,2] <= cutoffs[x[4],3] & 
           !is.na(test_data[,3])] 
    subset_2=test_data$Values_2[test_data[,1] == cutoffs[x[4],1] & 
           test_data[,2] >= cutoffs[x[4],2] & 
           test_data[,2] <= cutoffs[x[4],3] & 
           !is.na(test_data[,4])] 
    Mean_1=mean(subset_1) 
    Mean_2=mean(subset_2) 
    c(Mean_1, Mean_2) 
}) 

    #  [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [,14] [,15] [,16] [,17] [,18] [,19] [,20] 
    #[1,] NA NA NA NA NA NA NA NA NA  7 13.5 17 2.5  7 13.5 17 2.5  7 13.5 17 
    #[2,] NA NA NA NA NA NA NA NA NA 27 33.5 37 22.5 27 33.5 37 22.5 27 33.5 37 

#Running the same function, but subsetting below 9 rows it returns the correct values 
#apply(cutoffs[1:9,], 1, function(x){... 
#  1 2 3 4 5 6 7 8 9 
#[1,] 2.5 7 13.5 17 2.5 7 13.5 17 2.5 
#[2,] 22.5 27 33.5 37 22.5 27 33.5 37 22.5 

Я знаю, что для этого есть веская причина, но я не могу понять, что это такое. Любая помощь будет принята с благодарностью.

Если есть более элегантный способ сделать это, дайте мне знать. Фактический набор данных намного больше, эквивалент «отсечки» составляет около 3 тыс. Строк, а «test_data» - 250 тыс. Строк. Эта функция занимает много времени, поэтому я предполагаю, что есть намного лучшие способы сделать это.

+0

Можете ли вы показать ожидаемый выход? Это просто подмножество. – akrun

ответ

1

Во-первых, не использовать apply на кадре данных. Он преобразует df в матрицу, а это означает, что все столбцы будут принудительно введены в один тип. В частности, если какой-либо из столбцов является символом или фактором, результирующая матрица также будет символом.

Но это не проблема. Давайте посмотрим на первый код фрагмента вы представили:

subset1 <- test_data$Values_1[test_data[,1] == cutoffs[r,1] & 
           test_data[,2] >= cutoffs[r,2] & 
           test_data[,2] <= cutoffs[r,3] & 
           !is.na(test_data[,3])] 

И второй фрагменте кода:

subset_1 <- test_data$Values_1[test_data[,1] == cutoffs[x[4],1] & 
           test_data[,2] >= cutoffs[x[4],2] & 
           test_data[,2] <= cutoffs[x[4],3] & 
           !is.na(test_data[,3])] 
subset_2 <- test_data$Values_2[test_data[,1] == cutoffs[x[4],1] & 
           test_data[,2] >= cutoffs[x[4],2] & 
           test_data[,2] <= cutoffs[x[4],3] & 
           !is.na(test_data[,4])] 

Это не то же самое (что значение 4-го элемента x?). Предполагая, что первый фрагмент кода - это то, что вы хотите, тогда его применение по всем строкам будет выглядеть так.

sapply(seq_len(nrow(cutoffs)), function(r) { 
    vals1 <- test_data$Values_1[test_data[,1] == cutoffs[r,1] & 
           test_data[,2] >= cutoffs[r,2] & 
           test_data[,2] <= cutoffs[r,3] & 
           !is.na(test_data[,3])] 
    vals2 <- test_data$Values_2[test_data[,1] == cutoffs[r,1] & 
           test_data[,2] >= cutoffs[r,2] & 
           test_data[,2] <= cutoffs[r,3] & 
           !is.na(test_data[,3])] 
    c(mean(vals1), mean(vals2)) 
}) 

#  [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [,14] [,15] [,16] [,17] [,18] [,19] [,20] 
#[1,] 2.5 7 13.5 17 2.5 7 13.5 17 2.5  7 13.5 17 2.5  7 13.5 17 2.5  7 13.5 17 
#[2,] 22.5 27 33.5 37 22.5 27 33.5 37 22.5 27 33.5 37 22.5 27 33.5 37 22.5 27 33.5 37 
+0

Это работает! Спасибо. – JHegg

+0

Именно поэтому я понимаю, почему эта проблема произошла. 'apply (cutoffs, 1, function (x) {x})' возвращает всю строку для каждой итерации.Вот почему я использовал «x [4]», потому что четвертый столбец - это просто номер строки в последовательности. Является ли это чем-то внутренним для применения(), которое заставляет НС выходить после 10 итераций, что-то о вызове «x [4]» или что-то еще? – JHegg

+0

Если я правильно понял вас с первого столбца символа 'cutoffs's'is, то все столбцы становятся символами, используя apply(). Итак, поведение какое-то отношение к тому, как R работает с x [4], когда оно было повернуто к персонажу? Если так, то, что это? Я бы подумал, что в этом случае это не удастся для всех итераций. – JHegg