【问题标题】:How can I turn these multiple value assignment arguments into a function in R? Populate a column with species dependent values如何将这些多值赋值参数转换为 R 中的函数?使用物种相关值填充列
【发布时间】:2020-02-05 19:49:02
【问题描述】:

在我的工作中,我需要为一个新列分配一个分数。该分数的数值因物种而异。

目前我有以下方法可以实现这一点,但对于重复使用多个数据集来说不是很简洁:

bird$VIS <- 0 # creates the new column and populates it with 0 

bird$VIS[bird$species == "Tyto alba" ] <- 0.0502 # assigns this score to the VIS column for rows   where the species is "Tyto alba" 
bird$VIS[bird$species == "Branta leucopsis" ] <- 0.044 
bird$VIS[bird$species == "Ciconia nigra" ] <- 0.002
bird$VIS[bird$species == "Grus grus" ] <- 0.001
bird$VIS[bird$species == "Bubo bubo" ] <- 0.004513 
bird$VIS[bird$species == "Neophron percnopterus" ] <- 0.0015333
bird$VIS[bird$species == "Platalea leucorodia" ] <- 0.001

等等,总共有 26 个物种,但这个子样本应该足以证明我想要做什么。

我的问题本质上是我如何将它变成一个无论所有物种是否都存在于数据框中都可以工作的函数?

本质上,我希望能够编写如下内容,而不是使用上述顺序行分配:

assign_VIS_function(bird)

导致输出类似于:

SPECIES           VIS
Branta leucopsis  0.044
Tyto alba         0.0502
Tyto alba         0.0502
Tyto alba         0.0502
Tyto alba         0.0502
Gyps fulvus       0.22838
Gyps fulvus       0.22838
Gyps fulvus       0.22838

等等……

非常感谢。

【问题讨论】:

  • 你试过 ifelse() 逻辑吗?
  • 使用映射创建一个向量。像vec&lt;-c(Tyto alba=0.502, Branta leucopsis=0.044, ...) 这样的东西。然后试试vec[bird$species]
  • 创建一个查找表 - 一个包含species 列和VIS 列的数据框。您可以将其保存为 CSV 文件,查看它以验证值是否为您想要的值,根据需要对其进行编辑等。当您要将列添加到数据框时,merge 两个数据框,@ 987654329@
  • 使用case_when 来自dplyr

标签: r function variable-assignment


【解决方案1】:

正如@Gregor 提到的 SQL 语言,将指标数据保存在 查找表 中,然后将 merge 以一对多的关系保存到原始表中,该关系可扩展到 26 或 260 个项目:

species_vis_df <- data.frame(species = c("Tyto alba", "Branta leucopsis", "Ciconia nigra", 
                                         "Grus grus", "Bubo bubo", "Neophron percnopterus", 
                                         "Platalea leucorodia"),
                             value = c(0.0502 , 0.044, 0.002, 0.001, 
                                       0.004513, 0.0015333, 0.001))

或者。表格格式:

txt = 'species                 value
"Tyto alba"                   0.0502
"Branta leucopsis"             0.044
"Ciconia nigra"                0.002
"Grus grus"                    0.001
"Bubo bubo"                 0.004513
"Neophron percnopterus"    0.0015333
"Platalea leucorodia"          0.001'

species_vis_df <- read.table(text = txt, header=TRUE)
species_vis_df
#                 species     value
# 1             Tyto alba 0.0502000
# 2      Branta leucopsis 0.0440000
# 3         Ciconia nigra 0.0020000
# 4             Grus grus 0.0010000
# 5             Bubo bubo 0.0045130
# 6 Neophron percnopterus 0.0015333
# 7   Platalea leucorodia 0.0010000

然后运行merge,专门再次借用SQL left joinall.x=TRUE 合并以保留所有原始行,而不管与第二个表匹配。之后,进行必要的赋值(NA 不匹配的值)并删除查找值:

bird <- within(merge(bird, species_vis_df, by="species", all.x=TRUE), {
               VIS <- value
               rm(value)
        })

【讨论】:

  • 谢谢!这很有效,而且更简洁。
【解决方案2】:

您实际上可以提出一个非常简单的可重现示例,我在这里给出:

DT <- data.frame(V1 = LETTERS[1:10])

您想在新变量 (VIS) 上为 V1 的每个特定变量打分。

使用 case_when 的 dplyr 解决方案

library(dplyr)
DT = DT %>% 
  mutate(VIS=case_when(
    V1=="A"~0.1,
    V1=="B"~0.2 #and so on
  ))

DT

【讨论】:

    【解决方案3】:

    另一个使用 ifelse() 逻辑的例子。你看,如果你不为“Platalea leucorodia”或其他什么物种,它们将被归为 0(位于代码的最末尾)。

    data<-data_frame(birds=c("Grus grus","Bubo bubo","Grus grus","Bubo bubo","Platalea 
    leucorodia"))
    data %>%
      mutate(VIS = ifelse(birds == "Tyto alba", 0.0502 ,
                         ifelse(birds == "Branta leucopsis" ,  0.044 ,
                                ifelse(birds == "Ciconia nigra" , 0.002,
                                       ifelse(birds == "Grus grus", 0.001, 
                                              ifelse(birds == "Bubo bubo", 0.004513 , 0))))))
    

    【讨论】:

    • 这比 OP 问题中的代码效率低,而且恕我直言,可读性也较差。嵌套的 ifelse 写起来很糟糕,尤其是 OP 说它们有 26 个条件。
    • @Gregor 只是提供另一个视角
    • 但是为什么要提供一个糟糕的替代方案而没有任何关于它不好的评论呢?只是为了欺骗没有足够经验的人认为它不好使用它?
    • 不好的选择?这还不错,只是没有那么干净。但会正确完成工作。
    • 很糟糕。为 OPs 26 条件写出来,然后告诉我它还不错。编写更多的工作,更难阅读,更糟糕的调试,计算速度更慢,并且无法扩展。 (如果 OPs 问题扩展到超过 50 个条件,the method fails completely)。 在各个方面都比 OP 在问题中已有的选项更糟糕,这使得它成为一个糟糕的建议。
    猜你喜欢
    • 1970-01-01
    • 2018-05-12
    • 2018-07-24
    • 1970-01-01
    • 2015-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-07
    相关资源
    最近更新 更多