R-为数据中的每两列执行功能

时间:2018-08-21 17:13:16

标签: r maps lapply

我有一个包含许多(100+)对坐标的数据框

[lat1] [long2] [lat3] [long4] [..]  [..]
30.12    70.25    32.21    70.25  ..  ..
31.21    71.32    32.32    75.2   ..  ..
32.32    70.25    31.23    75.0   ..  ..

此函数在数据框的前两列中绘制一条连接坐标的线

lines(mapproject(x=data$long2, y=data$lat1), col=3, pch=20, cex=.1)

我需要在每对纬度/经度坐标上执行此功能,以便为每条纬度绘制一条新线/未连接线

看这个例子  Operate on every two columns in a matrix我认为我需要创建一个列表,如何为每个列对创建一个列表?

然后,我可以按https://nicercode.github.io/guides/repeating-things/所述使用lapply-如何将我的lines()调用包装在函数中?

完整脚本:

library(maps)
library(mapproj)

data <- read.csv("data.csv")

map('world', proj='orth', fill=TRUE, col="#f2f2f2", border=0, orient=c(90, 0, 0))

lines(mapproject(x=data$long, y=data$lat), col=3, pch=20, cex=.1)

更新的问题

在注释的帮助下,我尝试了一种每两列执行一次sapply的方法,该方法似乎可以按需工作。这是有待改进的地方

df <- data.frame(X1 = c(0, 10, 20), 
                   Y2 = c(80, 85, 90), 
                   X3 = c(3, 10, 15), 
                   Y4 = c(93, 100, 105), 
                   X5 = c(16, 20, 35),
                   Y6 = c(100, 105, 130))


map('world', proj='orth', fill=TRUE, col="#f2f2f2", border=0, orient=c(90, 0, 0))

sapply(seq(1,5,by=2),function(i) lines(mapproject(x = (df[,i]), y = (df[,(i+1)])), col = 3))

2 个答案:

答案 0 :(得分:0)

回复最新问题

此原始答案的更新不依赖于列名的任何内容,但确实依赖于cascadeValidate: false对中排序的列。由于deepValidate: true表示期望相反的坐标对,因此我在函数调用中对其进行了切换。

我也不假定列数。

save()

回复原始问题

我认为这可以满足您的要求

(latitude, longitude)

首先,从数据框列名称中获取唯一的整数集。然后,对于每个整数,应用一个函数,该函数选择与该整数匹配的2列并调用?mapproject

函数library(dplyr) library(stringr) library(maps) library(mapproj) lat_lons <- data.frame(lat1 = c(30, 31, 32), lon1 = c(70, 71, 70), lat2 = c(32, 32, 31), lon2 = c(70, 75, 75), lat3 = c(33, 33, 33), lon3 = c(72, 73, 74)) ints <- seq(1, ncol(lat_lons) - 1) map_lines <- function(int) { lines(mapproject(x = df[, int + 1], y = df[, int]), col = 3, pch = 20, cex = .1) } map('world', proj = 'orth', fill = TRUE, col = "#f2f2f2", border = 0, orient = c(90, 0, 0)) sapply(ints, map_lines) 不返回任何内容,但会作为副作用将线添加到活动绘图中。这不是一种理想的做事方式(我宁愿使用library(dplyr) library(stringr) library(maps) library(mapproj) lat_lons <- data.frame(lat1 = c(30, 31, 32), lon1 = c(70, 71, 70), lat2 = c(32, 32, 31), lon2 = c(70, 75, 75), lat3 = c(33, 33, 33), lon3 = c(72, 73, 74)) ints <- names(lat_lons) %>% str_extract("[0-9]") %>% unique() map_lines <- function(int) { df <- select(lat_lons, matches(int)) lines(mapproject(x = df[, 2], y = df[, 1]), col = 3, pch = 20, cex = .1) } map('world', proj = 'orth', fill = TRUE, col = "#f2f2f2", border = 0, orient = c(90, 0, 0)) sapply(ints, map_lines) 并在绘制情节之前将其组装在列表中),但它确实可行。

答案 1 :(得分:0)

您的编辑对我有用,但我可能会这样做,因为它的泛化效果更好。

library(maps)
library(mapproj)

df <- data.frame(X1 = c(0, 10, 20), 
                 Y2 = c(80, 85, 90), 
                 X3 = c(3, 10, 15), 
                 Y4 = c(93, 100, 105), 
                 X5 = c(16, 20, 35),
                 Y6 = c(100, 105, 130))

draw_lines <- function(df){

#Make sure we get the order right for iterating over length
 x  <- sort(grep("X", names(df), value = TRUE), decreasing = FALSE)
 y  <- sort(grep("Y", names(df), value = TRUE), decreasing = FALSE)

#Check for vector lengths to be the same
stopifnot(length(x) == length(y))

#I dont want to print anything to console
invisible(lapply(1 : length(x), function(j){
         lines(mapproject(x = df[, x[j]], y = df[, y[j]]), col = 3, pch = 20, cex = .1)
         })
         )
}

然后:

map('world', proj='orth', fill=TRUE, col="#f2f2f2", border=0, orient=c(90, 0, 0))
draw_lines(df = df)

希望这会有所帮助