【问题标题】:R: assign values to set of vectors based on conditions in another data frame of different lengthR:根据另一个不同长度的数据帧中的条件为向量集赋值
【发布时间】:2023-12-28 01:26:01
【问题描述】:

我想为存储在不同长度的不同数据帧中的最小/最大经度和纬度值的特定范围内的经度和纬度值分配一个段 ID。我的数据如下所示: 带有观察的数据框:

head(obs)
longitude latitude
52.06264 6.412816 
52.06097 6.413106 
51.06097 6.413346 
54.06097 6.413276
51.06089 6.413114
52.05444 6.413094

具有范围和段 ID 的数据框:

head(seg)
segment   lon_max  lon_min  lat_max  lat_min
01a       6.857822 6.857476 51.05837 51.03489
01b       6.858979 6.857834 51.03433 50.99901
01c       6.860019 6.858982 51.99836 51.96330
01d       6.860960 6.860050 51.96277 51.92718
01e       6.862294 6.860979 51.92657 51.89125
01f       6.863179 6.862301 51.89059 51.85562

对于每个观察点,我想知道它属于哪个“细分”,所以理想情况下我会得到这样的结果:

longitude latitude segment
52.03464 6.458816  1a
52.05667 6.416606  1a
51.06097 6.446346  1b
54.03757 6.413276  1c
51.06089 6.422114  1b
52.34243 6.413094  1a

我曾尝试仅使用纬度来执行此操作,但由于向量的长度不同,我收到一条错误消息。

obs[['segment']] <- for (i in obs$latitude) {
   if (i>=seg$lat_min & i<=seg$lat_max) {
     obs$segment=seg$segment
   } else {
     obs$segment='NA'}
}
  Error in `$<-.data.frame`(`*tmp*`, "segment", value = 1:118) : 
  replacement has 118 rows, data has 10284  

我知道为什么这行不通,因为它不能逐行匹配,但我不知道该怎么做。如何将每对纬度和经度与最小/最大值逐行匹配,直到找到它适合的范围并分配正确的 segment_ID?

提前致谢!

【问题讨论】:

  • 我认为您的 longitudelatitude 列在 obsseg 中混淆了

标签: r


【解决方案1】:

您的经度和纬度在两个数据框中都混淆了。

此外,您的示例数据无法匹配您的 obs 和 seg,因为例如,您的所有纬度 obs 都小于 lat_min 的查找 val。

尽管如此,这应该可行。您正在尝试查找表。

#create this so we have validation data
newline <- c( 51.05837, 6.857822)       
newobs <- rbind(obs, newline)

library(sqldf)
looked_up<-function(data, lookup){
data<-sqldf("select A.*,B.segment from
          data A left join lookup B 
          ON (A.longitude >= B.lon_min and A.longitude 
          <= B.lon_max and A.latitude >= B.lat_min and A.latitude 
          <= B.lat_max) ")
data
}

looked_up(newobs, seg)

#RESULTS
longitude latitude segment
1  52.06264 6.412816    <NA>
2  52.06097 6.413106    <NA>
3  51.06097 6.413346    <NA>
4  54.06097 6.413276    <NA>
5  51.06089 6.413114    <NA>
6  52.05444 6.413094    <NA>
7  51.05837 6.857822     01a

我在回答您的问题时发现这很有帮助。

http://shashiasrblog.blogspot.com/2014/01/excel-style-vlookup-and-rangelookup-in-r.html

【讨论】:

  • 非常感谢,这是一种享受!对不起,数据确实匹配,但还有更多案例,前六个不匹配。我应该检查并给你一些匹配的例子。但我很高兴你给了我一个可行的解决方案。
【解决方案2】:

给定一个向量x,其分量为“经度”和“纬度”,函数f 使用which.maxseg 中找到适当的行。那么apply(obs,1,f) 是长度为nrow(obs) 的向量,其中包含seg 中相应段的行号:

obs <- read.table( header = TRUE,
                 text =
"latitude longitude
52.06264 6.412816 
51.90089 6.861084
52.06097 6.413106 
51.06097 6.413346 
54.06097 6.413276
51.04097 6.857576
51.06089 6.413114
51.95089 6.860084
52.05444 6.413094" )

seg <- read.table( header = TRUE,
                   stringsAsFactors = FALSE,
                   text = 
"segment   lon_max  lon_min  lat_max  lat_min
01a       6.857822 6.857476 51.05837 51.03489
01b       6.858979 6.857834 51.03433 50.99901
01c       6.860019 6.858982 51.99836 51.96330
01d       6.860960 6.860050 51.96277 51.92718
01e       6.862294 6.860979 51.92657 51.89125
01f       6.863179 6.862301 51.89059 51.85562")


f <- function(x)
{
  which.max( c( ( seg["lon_min"] <= c(x["longitude"]) ) &
                ( seg["lon_max"] >  c(x["longitude"]) ) &
                ( seg["lat_min"] <= c(x["latitude"])  ) &
                ( seg["lat_max"] >  c(x["latitude"])  ),
                TRUE                                      ) )
}

X <- cbind( obs, segment = seg$segment[apply(obs,1,f)] )

结果:

> X
  latitude longitude segment
1 52.06264  6.412816    <NA>
2 51.90089  6.861084     01e
3 52.06097  6.413106    <NA>
4 51.06097  6.413346    <NA>
5 54.06097  6.413276    <NA>
6 51.04097  6.857576     01a
7 51.06089  6.413114    <NA>
8 51.95089  6.860084     01d
9 52.05444  6.413094    <NA>

【讨论】:

  • 非常感谢,这正是我一直在寻找的!抱歉,数据混淆了,但我没有意识到它们有问题。
最近更新 更多