R - список подмножеств data.frames по векторным значениям - PullRequest
1 голос
/ 14 апреля 2019

У меня есть список SpatialLinesDataFrames, и я хочу создать подмножество списка на основе сравнения значений со значениями в числовом векторе.

В частности, я хочу удалить элементы списка, в которых содержится одно из значенийв векторе в определенном столбце ('lineID') объекта data.frame.Воспроизводимый пример:

#create list of single-feature SpatialLineDataFrame
library(raster)
l1 <- cbind(c(0,3), c(0,3))
l2 <- cbind(c(0, 13), c(0, 1))
l3 <- cbind(c(0, 24), c(0,22.5))
l4 <- cbind(c(0, 1), c(0,13))
l5 <- cbind(c(0, 6), c(0,6))
Sldf <- spLines(l1, l2, l3, l4, l5, attr=data.frame(lineID=1:5))

sldfl <- list()
sldfl[[1]] <- Sldf[1,]
sldfl[[2]] <- Sldf[2,]
sldfl[[3]] <- Sldf[3,]
sldfl[[4]] <- Sldf[4,]
sldfl[[5]] <- Sldf[5,]

#create numeric vector
m <- c(1,3,5,7,10)

#attempt to keep only list elements that are not equal to any 
#of the values contained in vector
final <- list()
for (i in 1:length(sldfl)) {
  for (j in 1:length(m)) {
    if (factor(sldfl[[i]]@data$lineID) != m[j]) {
      final[[i]] <- sldfl[[i]]
    }}}

Результат цикла возвращает весь исходный список.Что не так с моей петлей?

1 Ответ

2 голосов
/ 14 апреля 2019

У вас, по сути, есть два вектора, ids и m:

> ids
[1] 1 2 3 4 5
> m
[1]  1  3  5  7 10

, и вы по сути выполняете это:

for(i in 1:length(ids)){
 for(j in 1:length(m)){
  if(i != m[j]){
    message("add ",i,j)
  }else{
    message("Not adding ",i,j)
  }
 }
}

Запустите это, и вы увидитеон добавляет множество элементов, потому что вы проверяете каждый идентификатор с каждым элементом в m, и по крайней мере один элемент m не входит в идентификатор, так что добавляется один (и более).

То, что вам действительно нужно, это:

for(i in 1:length(ids)){

  if(!(i %in% m)){
    message("add ",i,j)
  }else{
    message("Not adding ",i,j)
  }
 }

, который печатает:

Not adding 15
add 25
Not adding 35
add 45
Not adding 55

Добавляет элементы с ID 2 и 4, которые не входят в m.

В качестве альтернативы используйте базовую функцию R Filter, которая сокращает список с помощью функции элемента списка:

> Filter(function(L){!(L@data$lineID  %in% m)}, sldfl)
[[1]]
class       : SpatialLinesDataFrame 
features    : 1 
extent      : 0, 13, 0, 1  (xmin, xmax, ymin, ymax)
coord. ref. : NA 
variables   : 1
names       : lineID 
value       :      2 

[[2]]
class       : SpatialLinesDataFrame 
features    : 1 
extent      : 0, 1, 0, 13  (xmin, xmax, ymin, ymax)
coord. ref. : NA 
variables   : 1
names       : lineID 
value       :      4 
...