在我的工作中,我需要为新列分配一个分数。此分数的数值是特定于物种的。
目前,我有以下方法可以实现此目的,该方法有效,但对于多个数据集的重复使用不是很简洁:
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
等等...
非常感谢。
正如@Gregor提到的 SQL-speak 中,将指标数据保存在查找表中,然后以一对多关系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
,特别是再次借用 SQLleft join
与all.x=TRUE
合并以保留所有原始行,而不管与第二个表是否匹配。然后,进行所需的分配(NA
不匹配的值(并删除查找值:
bird <- within(merge(bird, species_vis_df, by="species", all.x=TRUE), {
VIS <- value
rm(value)
})
您实际上可以提出一个非常简单的可重现示例,我在这里给出:
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
另一个使用 ifelse(( 逻辑的例子。你看,如果你不为"普拉塔利亚"编码 白细胞"或它们将被归为 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))))))