Петля петли в R - PullRequest
       8

Петля петли в R

2 голосов
/ 11 января 2012

Это моя проблема: у меня есть два разных фрейма данных (A и B). Столбец каждого фрейма данных представляет собой географическое местоположение, а данные строки представляют собой виды в данном месте. Мне нужно пересечь список видов из местности 1 данных A с перечнем видов всех мест из фрейма данных B. Чтобы сделать это, я написал такой цикл:

res<-list()
for(i in 1:length(B)) {intersect(A[1], B[i])->res[[i]]
}

Теперь я должен повторить ту же петлю для населенного пункта 2, 3, 4, 5,6, ..... А, то есть я должен пересечь все населенные пункты А со всеми местностями B.

Спасибо.

Ответы [ 3 ]

5 голосов
/ 11 января 2012

Здесь аналогичен подход к вложенным циклам, который использует lapply().

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

Я рассмотрю пример, и вы, возможно, сможете адаптировать его к своемунабор данных.

Сначала создадим примерный фрейм данных 3x3 с именем df, со столбцами a, b и c и строками d, e и f:

> df <- data.frame(a = sample(3), b = sample(3), c = sample(3))
> rownames(df) <- c('d','e','f')

Давайте посмотрим на df и его транспонирование t(df):

> df
  a b c
d 3 1 3
e 1 3 1
f 2 2 2

> t(df)
  d e f
a 3 1 2
b 1 3 2
c 3 1 2

Допустим, мы хотим intersect векторы столбцов df и t(df),Теперь мы используем вложенные операторы lapply() для запуска intersect() для векторов столбцов как из df, так и из транспонирования t(df):

> result <- lapply(df, function(x) lapply(as.data.frame(t(df)), function(y) intersect(x,y)))

Результатом является list(), показывающий результаты пересечения:

> is.list(result)
[1] TRUE

> print(result)
$a
$a$d
[1] 3 1

$a$e
[1] 3 1

$a$f
[1] 2


$b
$b$d
[1] 1 3

$b$e
[1] 1 3

$b$f
[1] 2


$c
$c$d
[1] 3 1

$c$e
[1] 3 1

$c$f
[1] 2

Давайте снова посмотрим на df и t(df) и посмотрим, как читать эти результаты:

> df
  a b c
d 3 1 3
e 1 3 1
f 2 2 2

> t(df)
  d e f
a 3 1 2
b 1 3 2
c 3 1 2

Давайте посмотрим на df$a, пересекаемый с t(df)$d,t(df)$e и t(df)$f:

$a
$a$d
[1] 3 1

Пересекающиеся векторы a и d: {3,1,2}^{3,1,3} = {3,1}

$a$e
[1] 3 1

Снова с векторами a и e: {3,1,2}^{1,3,1} = {3,1}

$a$f
[1] 2

И наконец, с векторами a и f: {3,1,2}^{2,2,2} = {2}

Далее следуют другие элементы в result.

Чтобы расширить это на ваш набор данных, представьте, что ваши столбцы фрейма данных обозначены как localities , а столбцы транспонированных фреймов данных - как ваш вид .Затем используйте lapply(), как показано выше.


Чтобы разбить вложенный оператор lapply(), начните с внутреннего lapply():

lapply(as.data.frame(t(df)), function(y) ... )

Что это означаетчто каждый вектор столбца в t(df) - столбцы $ d, $ e и $ f - представлены переменной y в function(y).Мы вернемся к ... через секунду.

Теперь давайте посмотрим на внешний lapply():

lapply(df, function(x) ... )

Что это означает, что каждый столбец-вектор в df- столбцы $ a, $ b и $ c - представлены переменной x в function(x).

Теперь давайте объясним ....

Внешняя ... - это любая функция x - это может быть length(), sum() и т. Д. И даже другая lapply().Внутренний lapply() имеет свою собственную функцию и имя переменной y, поэтому внутренний ... может запускать функцию как на x, так и на y.

Итак, вот что мы делаем:каждый вектор столбца в df, мы запускаем функцию на этом df -векторе и каждый вектор столбца в транспонированной t(df).В нашем примере функция, которую мы будем запускать на x и y, равна intersect():

> result <- lapply(df, function(x) lapply(as.data.frame(t(df)), function(y) intersect(x,y)))
3 голосов
/ 11 января 2012

Трудно полностью понять, что вы хотите получить в результате. Но если я правильно угадал ваши потребности, приведенный ниже код будет делать то, что вы хотите. Этот код может быть дополнительно оптимизирован для повышения скорости, поскольку для больших наборов данных он может работать не слишком быстро.

res <- list()
for (i in 1:ncol(A)) {
  res[[i]] <- list()
  for (j in 1:ncol(B)) {
    res[[i]][[j]] <- intersect(A[,i], B[,j])
  }
}

Для доступа к результату вы можете использовать

res[[column_index_in_A]][[column_index_in_B]]
1 голос
/ 11 января 2012

Вот дикая догадка на ваших данных:

A <- data.frame(
  London     = c(TRUE, TRUE, FALSE),
  Manchester = c(FALSE, TRUE, FALSE),
  Birmingham = c(TRUE, FALSE, TRUE),  
  row.names  = c("rats", "mice", "foxes")
)

B <- data.frame(
    London     = c(TRUE, FALSE, FALSE),
    Manchester = c(TRUE, TRUE, TRUE),
    Birmingham = c(TRUE, TRUE, FALSE),
    row.names  = c("rats", "mice", "foxes")    
)


> A
      London Manchester Birmingham
rats    TRUE      FALSE       TRUE
mice    TRUE       TRUE      FALSE
foxes  FALSE      FALSE       TRUE
> B
      London Manchester Birmingham
rats    TRUE       TRUE       TRUE
mice   FALSE       TRUE       TRUE
foxes  FALSE       TRUE      FALSE

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

as.matrix(A) & as.matrix(B)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...