【问题标题】:R programming fail to run head() on a SpatialPointsDataFrameR 编程无法在 SpatialPointsDataFrame 上运行 head()
【发布时间】:2013-01-19 00:50:23
【问题描述】:

我需要将 R data.frame 对象转换为 SpatialPointsDataFrame 对象,以便对数据运行空间统计功能。但是,由于某种原因,将 data.frame 对象转换为 SpatialPointsDataFrame 在转换后的对象上运行特定函数时会出现意外行为。

在这个例子中,我尝试在生成的 SpatialPointsDataFrame 上运行 head() 函数 为什么函数 head() 在某些 SpatialPointsDataFrame 对象上失败?

这是重现该行为的代码。

示例1,没有错误:

#beginning of r code
#load S Classes and Methods for Spatial Data package "sp"
library(sp)
#Load an example dataset that contain geographic ccoordinates
data(meuse)
#check the structure of the data, it is a data.frame
str(meuse)
#>'data.frame':  155 obs. of  14 variables: ...
#with coordinates x,y
#Convert the data into a SpatialPointsDataFrame, by function coordinates()
coordinates(meuse) <- c("x", "y")
#check structure, seems ok
str(meuse)
#Check first rows of the data
head(meuse)
#It worked!
#Now create a small own dataset
testgeo <- as.data.frame(cbind(1:10,1:10,1:10))
#set colnames
colnames(testgeo) <- c("x", "y", "myvariable")
#convert to SpatialPointsDataFrame
coordinates(testgeo) <- c("x", "y")
#Seems ok
str(testgeo)
#But try running for instance head()
head(testgeo)
#Resulting output: Error in `[.data.frame`(x@data, i, j, ..., drop = FALSE) : 
#undefined columns selected
#end of example code

我不理解的两个示例数据集之间存在一些差异。函数 str() 不显示区别?

为什么函数 head() 在数据集 testgeo 上会失败?

添加更多列时为什么head()会起作用,10似乎是极限:

testgeo <- as.data.frame(cbind(1:10,1:10,1:10,1:10,1:10,1:10,1:10,1:10))
coordinates(testgeo) <- c("V1", "V2")
head(testgeo)

【问题讨论】:

    标签: r


    【解决方案1】:

    SpatialPoints/PolygonsDataFrames 没有特定的head 方法,因此当您调用head(testgeo)head(meuse) 时,它会使用默认方法:

    > getAnywhere("head.default")
    A single object matching ‘head.default’ was found
    It was found in the following places
      registered S3 method for head from namespace utils
      namespace:utils
    with value
    
    function (x, n = 6L, ...) 
    {
        stopifnot(length(n) == 1L)
        n <- if (n < 0L) 
            max(length(x) + n, 0L)
        else min(n, length(x))
        x[seq_len(n)]
    }
    <bytecode: 0x97dee18>
    <environment: namespace:utils>
    

    然后返回 x[1:n],但对于那些空间类,像这样的方括号索引需要列:

    > meuse[1]
            coordinates cadmium
    1  (181072, 333611)    11.7
    2  (181025, 333558)     8.6
    3  (181165, 333537)     6.5
    4  (181298, 333484)     2.6
    5  (181307, 333330)     2.8
    6  (181390, 333260)     3.0
    7  (181165, 333370)     3.2
    8  (181027, 333363)     2.8
    9  (181060, 333231)     2.4
    10 (181232, 333168)     1.6
    > meuse[2]
            coordinates copper
    1  (181072, 333611)     85
    2  (181025, 333558)     81
    3  (181165, 333537)     68
    4  (181298, 333484)     81
    5  (181307, 333330)     48
    6  (181390, 333260)     61
    7  (181165, 333370)     31
    8  (181027, 333363)     29
    9  (181060, 333231)     37
    10 (181232, 333168)     24
    

    因此,当您执行head(meuse) 时,它会尝试将meuse[1] 转换为meuse[6],因为meuse 有很多列。

    testgeo 没有。所以它失败了。

    真正的解决办法可能是写一个head.SpatialPointsDataFrame

    > head.SpatialPointsDataFrame = function(x,n=6,...){x[1:n,]}
    

    这样:

    > head(meuse)
           coordinates cadmium copper lead zinc  elev       dist   om ffreq soil
    1 (181072, 333611)    11.7     85  299 1022 7.909 0.00135803 13.6     1    1
    2 (181025, 333558)     8.6     81  277 1141 6.983 0.01222430 14.0     1    1
    3 (181165, 333537)     6.5     68  199  640 7.800 0.10302900 13.0     1    1
    4 (181298, 333484)     2.6     81  116  257 7.655 0.19009400  8.0     1    2
    5 (181307, 333330)     2.8     48  117  269 7.480 0.27709000  8.7     1    2
    6 (181390, 333260)     3.0     61  137  281 7.791 0.36406700  7.8     1    2
      lime landuse dist.m
    1    1      Ah     50
    2    1      Ah     30
    3    1      Ah    150
    4    0      Ga    270
    5    0      Ah    380
    6    0      Ga    470
    > head(testgeo)
      coordinates myvariable
    1      (1, 1)          1
    2      (2, 2)          2
    3      (3, 3)          3
    4      (4, 4)          4
    5      (5, 5)          5
    6      (6, 6)          6
    

    这里真正的问题是空间类不继承自data.frame,因此它们的行为与它们不同。

    【讨论】:

    • +1 感谢您解释 head 未按预期运行的原因。
    • 实际上真正的解决方法是转储 sp 类并做一些更像 PostGIS 所做的事情 - 有一个存储几何的列。我有一个概念证明,将几何图形存储为 WKT 文本,但要对其进行任何操作,我必须将其转换回 sp 类...
    【解决方案2】:

    head(meuse) 没有给你数据集meuse 的前几行,而是它的前几列(6 + 坐标列)。
    您的数据集 testgeo 只有 1 列,因此 head(testgeo) 失败。但是head(testgeo,1) 有效。

    head(testgeo,1)
       coordinates myvariable
    1       (1, 1)          1
    2       (2, 2)          2
    3       (3, 3)          3
    4       (4, 4)          4
    5       (5, 5)          5
    6       (6, 6)          6
    7       (7, 7)          7
    8       (8, 8)          8
    9       (9, 9)          9
    10    (10, 10)         10
    

    我不知道选择列而不是行的原因,但如果您想查看testgeo 的前几行,您可以使用更传统的:

    testgeo[1:5, ]
      coordinates myvariable
    1      (1, 1)          1
    2      (2, 2)          2
    3      (3, 3)          3
    4      (4, 4)          4
    5      (5, 5)          5
    

    【讨论】:

    • 感谢您的快速响应!
    【解决方案3】:

    sp 现在对所有Spatial 对象都有一个head 方法,实现为

    > sp:::head.Spatial
    function (x, n = 6L, ...) 
    {
        ix <- sign(n) * seq(abs(n))
        x[ix, , drop = FALSE]
    }
    

    请注意,它还可以处理负面的n

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-08-19
      • 2016-02-23
      • 2017-11-19
      • 2016-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-24
      相关资源
      最近更新 更多