【问题标题】:Add decimal after x digit R在 x 位 R 后添加小数
【发布时间】:2021-01-16 21:39:52
【问题描述】:

我有一个带有坐标的数据框(SWEREF_99,proj 3006),并意识到很多坐标的格式有误。

对于北方坐标,它们总是在逗号前有七位数字,而东方坐标在逗号前有六位数字,然后是十进制数字。喜欢:6789654.234(北)。但是,我的坐标看起来像这样; 6789654234。这意味着我想在数字 4 和 2 之间输入一个逗号/点。

我尝试过formatCformat,但是当我使用它时,我会添加多个逗号,例如 678.965.423.4,或者只是在十进制后添加零。

test

这是一个带有假想坐标的数据框,但它很好地描述了我的数据。

data <- data.frame(North = c(678645345, 675836578, 6573645.786), East = c(354674.47, 37465434, 4263546))

如您所见,我的一些坐标看起来不错,北坐标有 7 位数字,东坐标有 6 位数字。所以这些我不想改变,但只有那些不包含逗号的。

有人遇到过同样的问题吗?

【问题讨论】:

    标签: r format decimal coordinates proj


    【解决方案1】:

    在这种情况下,大多数情况下将数字作为字符串操作更容易。这应该可以解决您的问题:

    data <- data.frame(North = c(678645345, 675836578, 6573645.786), East = c(354674.47, 37465434, 4263546))
    
    insertComma <- function(data,commaPosition)
    {
      data.str <- as.character(data)
      data.comma <- ifelse(substr(data.str,commaPosition,commaPosition) != ".",paste0(substr(data.str,1,commaPosition - 1),".",
                                                                                      substr(data.str,commaPosition,nchar(data.str))),data.str)
      return(data.comma)
    }
    commaPositions <- c(8,7)
    
    sapply(seq_len(ncol(data)),function(col) insertComma(data[,col],commaPositions[col]))
    
         [,1]          [,2]       
    [1,] "6786453.45"  "354674.47"
    [2,] "6758365.78"  "374654.34"
    [3,] "6573645.786" "426354.6" 
    

    【讨论】:

      【解决方案2】:

      试试这个:

      within(data, {
        North = North / 10 ^ (nchar(trunc(North)) - 7L)
        East = East / 10 ^ (nchar(trunc(East)) - 6L)
      })
      

      【讨论】:

      • 谢谢!当我这样做时,我意识到所有小数都消失了。
      • 那些小数仍然存在。您看不到它们,因为它们被 R 隐藏,以便在控制台上进行漂亮的打印。您可以通过键入来查看它们,例如,as.character(data$North)。 @paula456
      • 好吧,我发现小数知道了!谢谢:)
      【解决方案3】:

      您可以使用正则表达式在特定位置插入小数点:

      transform(data, North = sub('(.{7})\\.?(.*)', '\\1.\\2', North), 
                      East = sub('(.{6})\\.?(.*)', '\\1.\\2', East))
      
      #        North      East
      #1  6786453.45 354674.47
      #2  6758365.78 374654.34
      #3 6573645.786  426354.6
      

      我们将数据分为 2 个捕获组。

      第一个捕获组(.{7}) - 捕获前 7 个字符

      \\.? - 可选的小数位(如果存在)之后将被忽略。

      第二个捕获组 ((.*)) 是之后的所有内容。

      我们返回两个带有反向引用的捕获组,在它们之间添加一个"." ('\\1.\\2')。

      同样的逻辑适用于East 列。

      【讨论】:

      • 哇,谢谢!这真的帮助了我。非常感谢。我对 R 还是很陌生,所以我只需要问一下。 ' 是什么意思?
      • 我想知道'登录'(.{7})\\.?(.*)', '\\1.\\2'。为什么要使用这些,它们有什么功能?
      • 这些是从字符串中捕获特定部分的正则表达式。我试图解释它在帖子中的作用。 ' 是一种类似于" 的字符串表示方式。
      • 好的,明白了!非常感谢您的帮助。我真的很感激。
      【解决方案4】:

      这似乎可行,使用来自 tidyverse 和 base-R 的基本函数(grepl、substr、paste、mutate、case_when)。如果你对正则表达式不满意,你可以试试这个:

      library(dplyr)
      
      data <- data.frame(North = c(678645345, 675836578, 6573645.786), East = c(354674.47, 37465434, 4263546))
      
      data %>%
        mutate(North = case_when(grepl(".", as.character(North), fixed = TRUE) ~ as.character(North),
                                 TRUE ~ paste0(substr(North,1,7),".",substr(North,8,nchar(North)))),
               East = case_when(grepl(".", as.character(East), fixed = TRUE) ~ as.character(East),
                                TRUE ~ paste0(substr(East,1,6),".",substr(East,7,nchar(East)))))
      

      输出:

              North      East
      1  6786453.45 354674.47
      2  6758365.78 374654.34
      3 6573645.786  426354.6
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-10-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-02-08
        • 1970-01-01
        • 2021-12-05
        • 1970-01-01
        相关资源
        最近更新 更多