2016-11-18 3 views
4

Я пытаюсь выполнить функцию для каждой ячейки таблицы данных в R, создавая вторую, основанную на результате этого цикла. Например, представьте, что у меня есть матрицаПрименить функцию к каждой ячейке матрицы в R

Ad1 Ad2 Ad3 Ad4 
    AA  6  0  10 
    AB  7  10  12 
    AC  0  0  15 

, и я пытаюсь создать матрицу B

Ad1 Ad2 Ad3 Ad4 
    AA  1  0  1 
    AB  1  0  1 
    AC  0  0  1 

таким образом, что каждая ячейка принимает значение 1, если ячейка имеет значение> 0 и сумму столбца минус, что ячейка также больше 0.

Например, AA ~ Ad2 равно 6, а сумма столбца равна 7 (6 + 7 + 0 - 6); то AA ~ Ad2 в матрице B принимает значение 1.

Есть ли способ выполнить это без выполнения цикла? Я сумел сделать это с помощью цикла, но это занимает слишком много времени:

A = read.table(text="Ad1 Ad2 Ad3 Ad4 
AA  6  0  10 
AA  7  10  12 
AA  0  0  15", header=TRUE) 

B = read.table(text="Ad1 Ad2 Ad3 Ad4 
AA  0  0  0 
AA  0  0  0 
AA  0  0  0", header=TRUE) 

for (i in 1:nrow(B)) { 
    for (j in 2:ncol(B)) { 
     if ((sum(A[,j], na.rm = T) - ifelse(is.na(A[i,j]), 0, A[i,j]))> 0 & 
     ifelse(is.na(A[i,j]), 0, A[i,j]) > 0) 
     {B[i,j] <- 1} 
    } 
} 

ответ

6

Мы можем сделать это без цикла путем создания двух логических матриц -1) Проверьте, есть ли больше 0 числовые значения столбцов (A[-1] > 0), 2) проверить, равна ли разница сумм столбца со значениями столбца больше 0. Если оба из них имеют значение ИСТИНА (&), преобразуйте логическую матрицу в двоичную (+) и назначьте ее подмножеству набор данных (A[-1])

A[-1] <- +(colSums(A[-1])[col(A[-1])]-A[-1]>0 & A[-1] > 0) 
A 
# Ad1 Ad2 Ad3 Ad4 
#1 AA 1 0 1 
#2 AB 1 1 1 
#3 AC 0 0 1 
+1

Спасибо; который работал просто отлично. – user1482923

1

Вот альтернативный основание R мет od в 2 строках. Первый вытягивает матрицу, которая может уменьшить копирование. Вторая строка вычисляет результат, сначала проверяя, что значения больше 0, а затем проверяет, что общий кол-во больше, чем каждый элемент. Эта часть выполняется частично через rep с каждым аргументом.

# extract matrix from data.frame 
myMat <- as.matrix(A[-1]) 
# calculate result and store in data.frame 
A[-1] <- (myMat > 0) * ((rep(colSums(myMat), each=nrow(myMat))- myMat) > 0) 
A 
    Ad1 Ad2 Ad3 Ad4 
1 AA 1 0 1 
2 AA 1 0 1 
3 AA 0 0 1 
1

Вот решение с использованием двух логических выражений оценивали на оригинальной матрицы:

(A > 0 & (colSums(A) - A > 0)) * 1.0

Левая сторона & проверки, что значения больше нуля, тогда как с правой стороны проверяет требования, касающиеся суммы столбца.

По себе каждый из них создает логическую матрицу того же размера, что и A. Затем & позволяет комбинировать логические матрицы для генерации нового, где ячейки имеют значение ИСТИНА, только если ячейки имеют значение ИСТИНА в обеих входных матрицах.

Наконец, * 1.0 приводит логическую матрицу в числовую.

+0

Вы также можете попробовать 'purrr :: keep (A, is.numeric)', чтобы сначала выбрать числовые столбцы. – Aramis7d

+0

Хорошее предложение - для data.frames Я обычно использовал что-то вроде 'x [, sapply (x, is.numeric)]'. Я имел в виду проверить «purrr». Похоже, что у него есть полезная функциональность! –

0

Вы также можете сделать:

m <- as.matrix(A[,-1]) 
colsm <- matrix(colSums(m), ncol = ncol(m), nrow = nrow(m), byrow = T) 
(colsm-m)>0 & m>0)*1 

# Ad2 Ad3 Ad4 
#[1,] 1 0 1 
#[2,] 1 0 1 
#[3,] 0 0 1 
Смежные вопросы