【问题标题】:Odd behaviour in replace()replace() 中的奇怪行为
【发布时间】:2019-03-26 11:48:46
【问题描述】:

我有一组环境数据 (env_PLI),其中一个变量是 season_year。该变量的两个值是“2016 年秋季”和“2017 年夏季”。为了进行分析,我需要将变量从字符更改为数字,因此我尝试更改它,以便级别仅为 2016 年和 2017 年。但是,代码

env_PLI$season_year <- replace(env_PLI$season_year,
                       c("autumn 2016", "summer 2017"), c(2016, 2017))

给我错误

Error in `$<-.data.frame`(`*tmp*`, season_year, value = c("autumn 2016",  : 
  replacement has 52 rows, data has 50

我尝试用谷歌搜索它,但结果没有多大帮助,因为他们似乎大多说需要在使用 replace() 之前创建变量,但在我的情况下,我在现有变量上使用它。我在这里还有什么错吗?

【问题讨论】:

    标签: r


    【解决方案1】:

    给定一个向量season_year &lt;- c("A", "autumn 2016", "summer 2017") 调用

    replace(season_year, c("autumn 2016", "summer 2017"), c(2016, 2017))
    

    结果

    #                                   autumn 2016   summer 2017 
    # "A" "autumn 2016" "summer 2017"        "2016"        "2017" 
    

    当您查看 replace 的作用时

    function (x, list, values) 
    {
        x[list] <- values
        x
    }
    

    您可能会发现自己的错误:您将两个条目附加到向量中。这就是错误“替换有 52 行,数据有 50 行”的原因(在数据框中,每一列中的条目数必须相同)。

    改用%in%

    replace(season_year, season_year %in% c("autumn 2016", "summer 2017"), c(2016, 2017))
    #[1] "A"    "2016" "2017"
    

    注意

    这种方法适用于上面的虚拟向量。如果 in 不适用于您的数据 1) 考虑给出一个最小的可重现示例,并且 2) 只需尝试

    env_PLI$season_year[env_PLI$season_year == "autumn 2016"] <- "2016"
    env_PLI$season_year[env_PLI$season_year == "autumn 2017"] <- "2017"
    

    或者试试

    env_PLI$season_year <- gsub("(autumn|summer)\\s+", "", env_PLI$season_year)
    # similar to @Moody_Mudskipper's second solution
    

    感谢@RichardTelford 和@Duckmayr。

    【讨论】:

    • 此解决方案将失败并显示season_year &lt;- c("A", "autumn 2016", "summer 2017", "summer 2017") plyr::mapvalues 直接替换原代码。
    • @RichardTelford 好点。不知道plyr::mapvalues。为什么不将您的评论变成答案?
    【解决方案2】:

    您可以考虑以下几种不同的选择:

    readr::parse_number(c("autumn 2016", "summer 2017"))
    # [1] 2016 2017
    gsub("\\D","",c("autumn 2016", "summer 2017")) # could be wrapped into as.numeric
    # [1] "2016" "2017"
    

    【讨论】:

      【解决方案3】:

      Marcus 解释了为什么您对 replace 有疑问,但他给出的解决方案在某些情况下会失败。

      有几种方法可以改变向量中的值。

      season_year <- c("A", "autumn 2016", "summer 2017", "summer 2017") 
      

      plyr::mapvalues 是您原始代码的直接替代品。当我在 data.frame 中拥有 from 和 to 向量时,我发现这最有用,就像字典一样。

      plyr::mapvalues(season_year, from = c("autumn 2016", "summer 2017"), to = c(2016, 2017))
      [1] "A"    "2016" "2017" "2017"
      

      dplyr::recode 接受新旧值对。

      dplyr::recode(season_year, "autumn 2016" = "2016", "summer 2017" = "2017")
      [1] "A"    "2016" "2017" "2017"
      

      您可以使用正则表达式来提取年份。 \\d{4} 查找四位数字的序列。当数据需要清洗时,正则表达式非常强大。

      gsub(pattern = ".*(\\d{4})", replacement = "\\1", season_year)
      [1] "A"    "2016" "2017" "2017"
      

      【讨论】:

        【解决方案4】:

        如果我误解了你的问题,请原谅我。

        library(tidyverse)
        dummydf<-data.frame(Id=c(1,2),Period=c("autumn 2006","spring 2007"))
        #Change to character
        dummydf %>% 
          mutate(Period=as.character(Period))
        #Back to numeric
        dummydf %>% 
          mutate(Period=as.numeric(Period))
        

        或者也许这个

        dummydf$Period %>% 
        str_replace_all("autumn","")
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-07-08
          • 2018-09-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多