【问题标题】:Trouble with nested ifelse statement in RR中嵌套ifelse语句的问题
【发布时间】:2020-05-28 14:22:38
【问题描述】:

我正在尝试在 R 中运行嵌套的 ifelse 语句。下面是使用 tidyverse 中的 glimpse() 函数查看我的数据结构:

Rows: 22,104
Columns: 9
$ `Formation/Locality`    <chr> "Montmartre", "Montmartre", "Montmartre", "Fur", "Me...
$ Location                <chr> "Ile-de-France Region, France", "Ile-de-France Regio...
$ Environment             <chr> "terrestrial", "terrestrial", "terrestrial", "offsho...
$ `Palaeolongitude(N/-S)` <dbl> 47.4, 47.4, 47.4, 52.3, 46.9, 42.9, 47.5, 46.9, 46.2...
$ `Palaeolatitude(E/-W)`  <dbl> 1.6, 1.6, 1.6, 5.4, 4.8, 1.9, -5.2, 4.8, -93.6, -111...
$ TaxonomicLevel          <chr> "Order", "Order", "Order", "Order", "Order", "Order"...
$ TaxonomicName           <chr> "Upupiformes", "Upupiformes", "Upupiformes", "Trogon...
$ MinMax                  <chr> "MaxMa", "MaxMa", "MaxMa", "MaxMa", "MaxMa", "MaxMa"...
$ Age                     <dbl> 37.2, 37.2, 37.2, 55.8, 48.6, 37.2, 48.6, 48.6, 55.8...

我试图让 R 查看Age 列,如果该值在一定范围内,它会将地质年龄名称放入一个名为AgeName 的新列中。如果该值不在该范围内,我希望它移动到下一个年龄范围,依此类推。到目前为止,这是我的代码:

pbdb_tidyish$AgeName <- ifelse(56>=pbdb_tidyish$Age&&47.8<pbdb_tidyish$Age,
                               "Ypresian",
                               ifelse(47.8>=pbdb_tidyish$Age&&41.2<pbdb_tidyish$Age,
                                      "Lutetian",
                                      ifelse(41.2>=pbdb_tidyish$Age&&37.8<pbdb_tidyish$Age,
                                             "Bartonian",
                                             ifelse(37.8>=pbdb_tidyish$Age&&33.9<=pbdb_tidyish$Age,
                                                    "Priabonian",NA))))

当我运行此代码时,它会创建新列,但会用"Priabonian" 填充整个列,因此数据集现在看起来像这样:

Rows: 22,104
Columns: 10
$ `Formation/Locality`    <chr> "Montmartre", "Montmartre", "Montmartre", "Fur", "Me...
$ Location                <chr> "Ile-de-France Region, France", "Ile-de-France Regio...
$ Environment             <chr> "terrestrial", "terrestrial", "terrestrial", "offsho...
$ `Palaeolongitude(N/-S)` <dbl> 47.4, 47.4, 47.4, 52.3, 46.9, 42.9, 47.5, 46.9, 46.2...
$ `Palaeolatitude(E/-W)`  <dbl> 1.6, 1.6, 1.6, 5.4, 4.8, 1.9, -5.2, 4.8, -93.6, -111...
$ TaxonomicLevel          <chr> "Order", "Order", "Order", "Order", "Order", "Order"...
$ TaxonomicName           <chr> "Upupiformes", "Upupiformes", "Upupiformes", "Trogon...
$ MinMax                  <chr> "MaxMa", "MaxMa", "MaxMa", "MaxMa", "MaxMa", "MaxMa"...
$ Age                     <dbl> 37.2, 37.2, 37.2, 55.8, 48.6, 37.2, 48.6, 48.6, 55.8...
$ AgeName                 <chr> "Priabonian", "Priabonian", "Priabonian", "Priabonia...

有人知道我哪里出错了吗?我认为它只是查看第一个 Age 值,运行 ifelse 语句,然后用结果填充整个列,而不是移动到下一行。

谢谢,

卡罗来纳

【问题讨论】:

  • 为什么是56&gt;=pbdb_tidyish$Age 而不是pbdb_tidyish$Age &gt;= 56
  • 或许case_when 是更好的选择。
  • 我还强烈建议在您的代码中使用更多空格 - 这将更易于阅读和调试。许多风格指南建议在二元运算符之间使用空格,例如,56&gt;=pbdb_tidyish$Age&amp;&amp;47.8&lt;pbdb_tidyish$Age 变为 56 &gt;= pbdb_tidyish$Age &amp;&amp; 47.8 &lt; pbdb_tidyish$Age

标签: r if-statement vectorization


【解决方案1】:

没有数据,不清楚这是否是唯一的错误,但你不应该在这里使用&amp;&amp;,因为它不是矢量化的。这意味着,它仅检查第一行中的值,仅基于此单一观察返回 TRUEFALSE,并回收此值。

请改用&amp;

比较见this answer

【讨论】:

  • 是的,这就是它的全部内容!谢谢!
【解决方案2】:

我认为,每当您发现自己在编写嵌套的 ifelse 语句时,您应该停下来问问自己是否有更好的方法来实现您想要做的事情。例如,以下单个函数调用可以实现您想要实现的功能,并且更易于理解和维护:

cut(pdb$tidyish, breaks = c(33.9, 37.8, 41.2, 47.8, 56),
    labels = c("Priabonian", "Bartonian", "Lutetian", "Ypresian"))

【讨论】:

    【解决方案3】:

    你已经在使用tidyverse,你应该熟悉case_when

    pbdb_tidyish <- pbdb_tidyish %>%
      mutate(AgeName = case_when(
        (Age >= 33.9 & Age <= 37.8) ~ 'Priabonian',
        (Age > 37.8 & Age <= 41.2) ~ 'Bartonian',
        (Age > 41.2 & Age <= 47.8) ~ 'Lutetian',
        (Age > 47.8 & Age <= 56) ~ 'Ypresian',
      ))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-09-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-03
      • 2014-07-12
      • 2015-08-10
      相关资源
      最近更新 更多