【问题标题】:Uniting within an ifelse statement在 ifelse 语句中合并
【发布时间】:2020-01-18 19:42:51
【问题描述】:

我正在尝试使用 unite 编写 ifelse 语句(if 语句也可以),这样如果 FPLACE 列中的字符数等于四个,它将创建一个名为“PLACE_ID”的新列联合FIPS 和 FPLACE(按此顺序,无空格)和(因为所有其他字符将等于 5)将 FPLACE 列中的剩余值与 FIPS_ST 和 FPLACE 合并,然后将这些值也放入“PLACE_ID”列。

在过去的一个小时里,我一直在尝试这种形式:

ifelse(nchar(dat$FPLACE, type = "chars")==4, 
       dat%>%unite(PLACE_ID, FIPS, FPLACE, sep = "", remove = FALSE), 
       dat%>%unite(PLACE_ID, FIPS_ST, FPLACE, sep = "", remove = TRUE))

开始更简单:

nchar(dat$FPLACE, type = "chars")==4, 

这行得通,但后来我尝试下面的代码,但出了点问题。

if(dat$FPLACE==nchar(4)){
  print(
dat%>%unite(PLACE_ID, FIPS, FPLACE, sep = "", remove = FALSE))
}

理想情况下,我可以只使用管道,但即使这样也行不通:

dat%>%nchar(.$FPLACE, type = "chars")==4

而且我认为在我不断的困惑中隐藏着一些既基本又重要的东西。为什么 dat%>%filter(variable=="something") 会起作用,但 dat%>%nchar(.$variable)==4 不会?我也从来没有弄清楚什么时候必须使用 .$ 与什么时候不需要。押韵和理由是什么?

非常感谢!!!

在这里输入:

Show in New WindowClear OutputExpand/Collapse Output
structure(list(X1 = c(1, 2, 3), FSTATE = c("(01) Alabama", "(01) Alabama", 
"(01) Alabama"), FCOUNTY = c(1, 1, 1), FPLACE = c(3220, 62328, 
62328), FIPS_ST = c("01", "01", "01"), FIPS_COUNTY = c("001", 
"001", "001"), FIPS = c("01001", "01001", "01001"), ORI9 = c("AL0040200", 
"AL0040100", "AL0040300"), ORI7 = c("AL00402", "AL00401", "-1"
), NAME = c("AUTAUGAVILLE POLICE DEPARTMENT", "PRATTVILLE POLICE DEPARTMENT", 
"PRATTVILLE FIRE DEPT ARSON INVESTIGATION BRANCH")), class = c("spec_tbl_df", 
"tbl_df", "tbl", "data.frame"), row.names = c(NA, -3L), spec = structure(list(
    cols = list(X1 = structure(list(), class = c("collector_double", 
    "collector")), FSTATE = structure(list(), class = c("collector_character", 
    "collector")), FCOUNTY = structure(list(), class = c("collector_double", 
    "collector")), FPLACE = structure(list(), class = c("collector_double", 
    "collector")), FIPS_ST = structure(list(), class = c("collector_character", 
    "collector")), FIPS_COUNTY = structure(list(), class = c("collector_character", 
    "collector")), FIPS = structure(list(), class = c("collector_character", 
    "collector")), ORI9 = structure(list(), class = c("collector_character", 
    "collector")), ORI7 = structure(list(), class = c("collector_character", 
    "collector")), NAME = structure(list(), class = c("collector_character", 
    "collector")), UA = structure(list(), class = c("collector_double", 
    "collector")), STATENAME = structure(list(), class = c("collector_character", 
    "collector")), COUNTYNAME = structure(list(), class = c("collector_character", 
    "collector")), UANAME = structure(list(), class = c("collector_character", 
    "collector")), PARTOF = structure(list(), class = c("collector_character", 
    "collector")), AGCYTYPE = structure(list(), class = c("collector_character", 
    "collector")), SUBTYPE1 = structure(list(), class = c("collector_character", 
    "collector")), SUBTYPE2 = structure(list(), class = c("collector_character", 
    "collector")), GOVID = structure(list(), class = c("collector_double", 
    "collector")), LG_NAME = structure(list(), class = c("collector_character", 
    "collector")), ADDRESS_NAME = structure(list(), class = c("collector_character", 
    "collector")), ADDRESS_STR1 = structure(list(), class = c("collector_character", 
    "collector")), ADDRESS_STR2 = structure(list(), class = c("collector_character", 
    "collector")), ADDRESS_CITY = structure(list(), class = c("collector_character", 
    "collector")), ADDRESS_STATE = structure(list(), class = c("collector_character", 
    "collector")), ADDRESS_ZIP = structure(list(), class = c("collector_double", 
    "collector")), REPORT_FLAG = structure(list(), class = c("collector_character", 
    "collector")), CSLLEA08_ID = structure(list(), class = c("collector_double", 
    "collector")), LEMAS_ID = structure(list(), class = c("collector_character", 
    "collector")), U_STATENO = structure(list(), class = c("collector_character", 
    "collector")), U_CNTY = structure(list(), class = c("collector_double", 
    "collector")), U_POPGRP = structure(list(), class = c("collector_character", 
    "collector")), U_TPOP = structure(list(), class = c("collector_double", 
    "collector")), LG_POPULATION = structure(list(), class = c("collector_double", 
    "collector")), CSLLEA_SUB = structure(list(), class = c("collector_character", 
    "collector")), COMMENT = structure(list(), class = c("collector_character", 
    "collector")), INTPTLAT = structure(list(), class = c("collector_double", 
    "collector")), INTPTLONG = structure(list(), class = c("collector_double", 
    "collector")), CONGDIST1 = structure(list(), class = c("collector_character", 
    "collector")), CONGDIST2_18 = structure(list(), class = c("collector_character", 
    "collector")), DISTNAME = structure(list(), class = c("collector_character", 
    "collector")), SOURCE_CSLLEA2008 = structure(list(), class = c("collector_double", 
    "collector")), SOURCE_UCR2010 = structure(list(), class = c("collector_double", 
    "collector")), SOURCE_UCR2011 = structure(list(), class = c("collector_double", 
    "collector")), SOURCE_UCR2012 = structure(list(), class = c("collector_double", 
    "collector")), SOURCE_NCIC2012 = structure(list(), class = c("collector_double", 
    "collector")), SOURCE_VENDOR = structure(list(), class = c("collector_double", 
    "collector"))), default = structure(list(), class = c("collector_guess", 
    "collector")), skip = 1), class = "col_spec"))

【问题讨论】:

    标签: r if-statement dplyr


    【解决方案1】:

    我不确定unite 是否可以这样使用,但您可以执行以下操作:

    library(tidyverse)
    
    dat %>% 
      mutate(PLACE_ID = ifelse(nchar(FPLACE, type="chars")==4, 
                               paste0(FIPS, FPLACE),
                               paste0(FIPS_ST, FPLACE)))
    

    关于您的过滤问题,您可以通过返回一个逻辑值向量来过滤dplyr 管道。例如:

    dat %>% filter(nchar(FPLACE, type = "chars")==4)
    

    这是可行的,因为nchar(dat$FPLACE, type = "chars")==4 返回一个逻辑值向量。您只需将其放在filter 中并删除dat$,因为数据帧已经通过管道传递到filter,您不需要(也不应该)显式引用数据帧名称。

    更一般地说,当引用 dplyr 管道中数据框的列名时(即,使用 filtermutate、@ 等函数时,您不需要(也不应该)使用 data.frame.name$ 987654333@ 和 summarise)。只需使用裸列名称即可。

    例如,看看如果您使用内置的mtcars 数据框执行以下操作会发生什么:

    mtcars %>% 
      group_by(cyl) %>% 
      summarise(mean1 = mean(mtcars$mpg),
                mean2 = mean(mpg))
    
        cyl mean1 mean2
      <dbl> <dbl> <dbl>
    1     4  20.1  26.7
    2     6  20.1  19.7
    3     8  20.1  15.1
    
    mean(mtcars$mpg)
    
    [1] 20.09062
    

    为了计算mean1,我们使用mtcars$mpg 而不是裸列名。这会在管道上下文(编程术语中管道的“环境”)之外到达全局环境中的 mtcars 版本,而不是使用由管道。因此,我们得到的是整体平均值,而不是我们想要的分组平均值。

    【讨论】:

    • 谢谢,这真的很有帮助。您的解决方案无缝运行。关于我的问题,我想我本来可以更清楚,我刚才又遇到了这个问题。例如,在使用您的代码时,如果我尝试在它的末尾添加 trimws(),它将无法正常工作......为什么会这样?: dat %>% mutate(PLACE_ID = ifelse(nchar(FPLACE , type="chars")==4, paste0(FIPS, FPLACE), paste0(FIPS_ST, FPLACE)))%>%trimws(PLACE_ID)
    • 使用mutate 更改管道中的列或创建新列:%&gt;% mutate(PLACE_ID = trimws(PLACE_ID))
    • This tutorial 介绍了使用 dplyr 和管道的基础知识。
    • 谢谢!我将浏览本教程...我可能应该比我更多地使用 mutate ——我主要在创建新变量和更改当前变量时使用它。
    【解决方案2】:

    只是为 case_when 插入一个插件,如果你扩展你的条件,它会更具可读性,并且通常会导致更少的意外行为,这是那个版本:

    data %>% 
      mutate(PLACE_ID = case_when(
        nchar(as.character(FPLACE)) == 4 ~ paste0(FIPS,FPLACE),
        nchar(as.character(FPLACE)) == 5 ~ paste0(FIPS_ST,FPLACE),
        TRUE                             ~ NA_character_
        )
      )
    

    ~ 的左边是你的条件,右边是当它评估为真时使用的条件。事情是按顺序评估的,直到您的 TRUE(显然,它总是评估为 TRUE)。

    至于您关于 dplyr 和管道的问题,正如 eipi10 所说,dplyr 函数在向量上工作,并假设通过管道传输的任何内容都是您要评估的数据。美元符号只是 data[["named_item"]] 的简写,它只是在数据帧的情况下拉出命名列。它本质上与将 c(1,2,3) 之类的任意向量传递给 dplyr 中的函数相同; dplyr 函数会将其视为静态而不是向量化的东西,这就是上面 eipi10 示例中的方法不同的原因。如果您有兴趣,这里有一些关于 R 中访问器的更多信息: https://www.r-bloggers.com/r-accessors-explained/

    【讨论】:

    • 谢谢——刚刚找到了一个可以使用 case_when 的实例。工作得很漂亮。也感谢您对我的其他问题的跟进...链接总是很感激!
    • "It's essentially the same as passing an arbitrary vector like c(1,2,3) to a function in dplyr; dplyr functions will treat it as static instead of something to vectorize over, which is why the means differ in eipi10's example above.":我不认为这是正确的。例如,当您这样做时,mean(mtcars$mpg)mean(mpg)(我的答案中的示例),您正在从 不同的 数据帧访问 mpg:第一个是 mtcars 在全球环境。第二个是通过管道传入mutate的数据帧。它与矢量化无关。
    • eipi10,分组为每个组创建单独的向量,以便在您传递列时进行向量化,据我所知。我不认为它们是不同的输入——这就是为什么第一个是多个向量被向量化,而第二个是单个向量不是。它也不是真正重要的数据框,因为您在这两种情况下都在提取向量。另外,您会发现,如果从管道/分组数据框中提取 .$mpg,您仍然会得到一个向量。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-03-08
    • 1970-01-01
    • 2013-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-17
    相关资源
    最近更新 更多