【问题标题】:If 2 columns of data have the same values in the row above it, then add 0.00001 to it如果 2 列数据在其上方的行中具有相同的值,则向其添加 0.00001
【发布时间】:2021-08-04 01:40:50
【问题描述】:

我有一个数据框,其中包含一个纬度列和一个经度列,如下所示

test <- data.frame("Latitude" = c(45.14565, 45.14565, 45.14565, 45.14565, 33.2222, 
31.22122, 31.22122), "Longitude" = c(-105.6666, -105.6666, -105.6666, -104.3333, 
-104.3333, -105.77777, -105.77777))

我想让每个值精确到小数点后 5 位,并检查纬度和经度对是否与其上方的对相同,将纬度和经度值都添加 0.00001。所以我的数据会变成这样:

test_updated <- data.frame("Latitude" = c(45.14565, 45.14566, 45.14567, 45.14565, 
33.22220, 31.22122, 31.22123), "Longitude" = c(-105.66660, -105.66661, -105.66662, 
-104.33330, -104.33330, -105.77777, -105.77778))

【问题讨论】:

标签: r loops decimal


【解决方案1】:

这是一种更新 test 中的 Latitude 列以重现 OP 的预期结果的方法:

options(digits = 8) # required to print all significant digits of Longitude
library(data.table)
setDT(test)[, `:=`(Latitude  = Latitude  + (seq(.N) - 1) * 0.00001,
                   Longitude = Longitude + (seq(.N) - 1) * 0.00001), 
            by = .(Latitude, Longitude)]
test
   Latitude  Longitude
1: 45.14565 -105.66660
2: 45.14566 -105.66659
3: 45.14567 -105.66658
4: 45.14565 -104.33330
5: 33.22220 -104.33330
6: 31.22122 -105.77777
7: 31.22123 -105.77776

比较

test_updated
  Latitude  Longitude
1 45.14565 -105.66660
2 45.14566 -105.66661
3 45.14567 -105.66662
4 45.14565 -104.33330
5 33.22220 -104.33330
6 31.22122 -105.77777
7 31.22123 -105.77778

差异是由 OP 要求 在纬度和经度值上添加 0.00001 和 OP 的预期结果造成的 0.00001 已从 经度值中减去

编辑

为了重现预期结果,必须考虑值的符号。不幸的是,基本 R sign() 函数为 sign(0) 返回零。所以,我们改用fifelse(x &lt; 0, -1, 1)

另外,我们可以接Henrik's splendid idea使用rowid()功能来避免分组。

options(digits = 8) # required to print all significant digits of Longitude
library(data.table)
cols <- c("Latitude", "Longitude")
setDT(test)[, (cols) := lapply(.SD, \(x) x + fifelse(x < 0, -1, 1) * 
                                 (rowidv(.SD, cols) - 1) * 0.00001), .SDcols = cols]
test
   Latitude  Longitude
1: 45.14565 -105.66660
2: 45.14566 -105.66661
3: 45.14567 -105.66662
4: 45.14565 -104.33330
5: 33.22220 -104.33330
6: 31.22122 -105.77777
7: 31.22123 -105.77778

【讨论】:

  • test[, Latitude := Latitude + (rowid(Latitude, Longitude) - 1) * 0.00001],避免by
  • @Henrik,好主意!
【解决方案2】:

像往常一样,不需要使用循环:

library(dplyr)
test_updated = test %>% 
    mutate(
        across(c(Latitude, Longitutde), 
            function(x) if_else(x == lag(x), x+0.00001, x)
            )
        )

format(round(test_updated, 5), nsmall = 5)
  Latitude Longitutde
1 45.14566 -105.66659
2 45.14566 -105.66659
3 45.14566 -105.66659
4 45.14566 -104.33329
5 33.22221 -104.33329
6 31.22123 -105.77776
7 31.22123 -105.77776

【讨论】:

    【解决方案3】:

    不确定我是否理解正确,但可能是这样的?

    rm(list=ls())
    
    n <- nrow(test)
    test_updated <- data.frame(Latitude = double(n),
                           Longitude = double(n))
    
    add <- 0.00001
    test_updated[1,] <- test[1,]
    for (i in 2:nrow(test)){
      if(test$Latitude[i-1] == test$Latitude[i] & test$Longitutde[i-1] == test$Longitutde[i]){
        test_updated$Latitude[i] <- test$Latitude[i] + add
        test_updated$Longitude[i] <- test$Longitutde[i] + add
       } else{
         test_updated[i,] <- test[i,]
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2021-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-08-13
      • 2020-11-03
      相关资源
      最近更新 更多