#r #loops #matrix #dataframe #multiple-columns
#r #циклы #матрица #фрейм данных #многоколоночный
Вопрос:
Я пытаюсь выполнить цикл по фрейму данных из столбцов, и вычисленный результат помещается в матрицу.
Сценарий может быть воспроизведен со следующими примерами данных:
df = data.frame(replicate(10,sample(0:20,10,rep=TRUE))) # the columns to be calculated on
M1 = as.data.frame(matrix(0, nrow = 10, ncol = 10)) # a matrix to hold the results.
rownames(M1) = colnames(df)
colnames(M1) = colnames(df)
И выглядят следующим образом:
> df # Frame with columns of data, X1 to X10
X1 X2 X3 X4 X5 X6 X7 X8 X9 X10
1 1 19 2 6 6 5 0 2 5 10
2 16 7 14 16 16 18 11 2 18 11
3 7 6 11 4 4 1 18 11 10 16
4 20 2 4 20 4 6 10 5 16 7
5 9 8 16 19 11 2 14 7 13 7
6 5 16 6 8 20 15 5 11 4 0
7 11 16 12 8 18 20 20 20 10 14
8 17 14 10 4 3 10 13 11 5 1
9 9 20 10 5 1 7 12 10 5 6
10 8 14 3 14 20 10 17 20 9 14
> M1 # Output frame to hold results
X1 X2 X3 X4 X5 X6 X7 X8 X9 X10
X1 0 0 0 0 0 0 0 0 0 0
X2 0 0 0 0 0 0 0 0 0 0
X3 0 0 0 0 0 0 0 0 0 0
X4 0 0 0 0 0 0 0 0 0 0
X5 0 0 0 0 0 0 0 0 0 0
X6 0 0 0 0 0 0 0 0 0 0
X7 0 0 0 0 0 0 0 0 0 0
X8 0 0 0 0 0 0 0 0 0 0
X9 0 0 0 0 0 0 0 0 0 0
X10 0 0 0 0 0 0 0 0 0 0
В df
столбцы X1 и X2 помещаются в вычисление, затем X1 и X3, затем X1 и X4 и т.д. Затем цикл будет повторять X2 и X3, затем X2 и X4 и т.д.
Столбцы n и m вводятся в вычисление / цикл, и результат должен быть помещен в соответствующее место в матрице, которое соответствует столбцу n x m. Само вычисление просто определяет область между Xn и Xm в виде нанесенных линий. Я не уверен, как правильно построить цикл для этого:
# The first iteration of the calculation, column X1 and X2 (X1 and X1 would = 0)
y = seq(1,10,1)
f1 = approxfun(y, df[,1] - df[,2]) # takes two columns as inputs
f2 = function(x) abs(f1(x))
area1 = integrate(f2, 1, 10, subdivisions = 500)
M1[2,1] = area1$value
Результирующий фрейм создаст «полуматрицу» (это все, что необходимо, поскольку зеркальная половина будет идентичной):
> M1
X1 X2 X3 X4 X5 X6 X7 X8 X9 X10
X1 0 0 0 0 0 0 0 0 0 0
X2 A 0 0 0 0 0 0 0 0 0
X3 A A 0 0 0 0 0 0 0 0
X4 A A A 0 0 0 0 0 0 0
X5 A A A A 0 0 0 0 0 0
X6 A A A A A 0 0 0 0 0
X7 A A A A A A 0 0 0 0
X8 A A A A A A A 0 0 0
X9 A A A A A A A A 0 0
X10 A A A A A A A A A 0
Я начал создавать цикл for, но я не могу использовать i и j, чтобы удерживать X1 до тех пор, пока он не пройдет через X2-X10, затем перейдет к X2 и т.д.
Спасибо!
Комментарии:
1. Когда я пытаюсь запустить
f1 = approxfun(y, df[,1] - df[,2])
, я получаю:Error in xy.coords(x, y) : object 'y' not found
. Являются ли функции f1 и f2 фактическими функциями, которые вы пытаетесь запустить на своих данных?2. Можете ли вы предоставить фактический вычисленный результат, возможно, только для матрицы 4×4?
3. @biomiha Извиняюсь, я не включил детали ‘y’ в свое объяснение, а также внес изменения в расчет как таковой. Для целей этого вопроса предполагалось, что это уменьшенная версия оригинала.
Ответ №1:
Я не смог заставить ваши функции работать. Итак, с использованием функции случайной замены этот цикл работает для меня:
area=list() # because the actual function doesn't work
for(i in 1:ncol(df)){
for(j in 1:ncol(df)){
if(i==j){M[i,i]=0;next}
selection=df[,c(i,j)]
#area=integrate(f2, 1, 200, subdivisions = 500)
area$value=mean(colSums(selection)) # something random to check
M[i,j]=area$value
M[j,i]=area$value
}
}
Но цикл, как правило, не самый эффективный способ выполнения задач. Таким образом, вы можете предпочесть этот вариант:
df = data.frame(replicate(10,sample(0:20,10,rep=TRUE))) # the columns to be calculated on
my.f = function(x) abs(x[,1]-x[,2])
#y = t(as.matrix(combn(ncol(df), 2L, function(y) integrate(my.f(df[y]), 1, 200, subdivisions = 500),simplify=F))) # This doesn't work, but should be close to what you want to do
y = t(as.matrix(combn(ncol(df), 2L, function(y) mean(f(df[y]),simplify=F)))) # this works, but is just an example
N = seq_len(ncol(y))
nams = colnames(df)
M = matrix(ncol = length(nams), nrow = length(nams))
M[lower.tri(M)] = y
M = t(out)
M[lower.tri(M)] = y
M = t(M)
diag(M) = 0
rownames(M) = colnames(out) = colnames(df)
M
X1 X2 X3 X4 X5 X6 X7 X8 X9 X10
X1 0.0 8.6 6.4 8.8 7.1 6.6 7.0 4.0 7.0 3.7
X2 8.6 0.0 5.0 4.4 5.5 5.4 4.4 9.2 8.0 7.7
X3 6.4 5.0 0.0 7.2 5.9 5.8 7.6 7.0 10.4 6.5
X4 8.8 4.4 7.2 0.0 5.9 4.4 5.4 9.6 8.4 7.3
X5 7.1 5.5 5.9 5.9 0.0 7.3 5.3 9.1 8.5 8.0
X6 6.6 5.4 5.8 4.4 7.3 0.0 6.0 8.4 5.6 3.7
X7 7.0 4.4 7.6 5.4 5.3 6.0 0.0 8.8 4.4 5.7
X8 4.0 9.2 7.0 9.6 9.1 8.4 8.8 0.0 9.6 6.9
X9 7.0 8.0 10.4 8.4 8.5 5.6 4.4 9.6 0.0 5.5
X10 3.7 7.7 6.5 7.3 8.0 3.7 5.7 6.9 5.5 0.0
Комментарии:
1. Спасибо за несколько решений @Wave, я только сейчас получаю возможность попробовать и реализовать это, поэтому я вернусь с результатами. Как я упоминал в комментарии выше, я кое-что упустил из расчета, который я отредактировал в исходном вопросе, мои извинения.
2. Я смог реализовать ваше первое предложение по моим исходным данным и функции, с образцом 3×3, это сработало хорошо, спасибо! Я пробую второе предложение, учитывая, что оно кажется более эффективным (и мое предполагаемое приложение будет размером 100×100 и больше). Как я могу адаптировать
y = t...
строку кода для моих исходных данных, которые представляют собой десятичные значения? Я предполагаю, что2L
относится к образцу, который является целыми числами. Спасибо.3. Вам нужно только изменить функцию. 2L относится к количеству элементов для выбора (2 столбца) и не должно быть изменено для вашего примера.