filter()(dplyr)不区分字符和数字?

filter() (dplyr) does not distinguish between character and number?

我正在将函数 filter()(在库 dplyr 中)与 this dataset 一起使用。它包含一个名为“depth_m”的变量,它是数字,我将它转换为字符 class 和 sapply(请参见下面的代码)并且我没有遇到问题。

但是现在变量是一个字符,当我根据“depth_m”变量过滤数据集时 =="20"(作为字符)或 == 20(作为数字)我得到了相同的结果所以..按数字(== 20)过滤时我不应该得到错误吗?

这是我的代码:

data <- read.table("env.txt", sep = "\t", header = TRUE)

class(data$depth_m)

输出:

[1] "integer"
# Variable transformation

data$depth_m <- sapply(data$depth_m, as.character)
class(data$depth_m)

输出:

[1] "character"

检查数据类型:

class(data$depth_m)

输出:

[1] "1000" "500"  "20"   "1"    "1000" "500"  "20"   "1"    "1000" "320"  "1"    "20"   "1"   
[14] "20"   "1"    "120"  "20"   "20"   "365"  "20"   "1"    "375"  "20"   "1"    "1000" "500" 
[27] "20"   "1"    "200"  "20"   "1"    "1000" "500"  "25"   "1"    "1000" "500"  "25"   "1"   
[40] "20"   "300"  "20"   "1000" "20"  

这里我在过滤。在此代码中,我希望获得一些子数据集,因为值“20”是一个字符并且它是正确的,因为它存在于原始数据集中。

y <- filter(data,  depth_m == "20") %>%
  select(env_sample, depth_m)
head(y)

输出:

   env_sample depth_m
1 Jan_B16_0020      20
2 Jan_B08_0020      20
3 Mar_M03_0020      20
4 Mar_M04_0020      20
5 Mar_M05_0020      20
6 Mar_M06_0020      20

我又来过滤了。在这段代码中,我没想到会得到一些子数据集,因为值 20 是一个数字,它不正确,因为它不存在于原始数据集中。

y1 <- filter(data, depth_m == 20) %>%
  select(env_sample, depth_m)
head(y1)

输出:

    env_sample depth_m
1 Jan_B16_0020      20
2 Jan_B08_0020      20
3 Mar_M03_0020      20
4 Mar_M04_0020      20
5 Mar_M05_0020      20
6 Mar_M06_0020      20

任何评论都会有所帮助。谢谢。

在 R 中,表达式 20 == "20" 是有效的,尽管有些人(来自其他编程语言)可能认为这有点“草率”。评估时,它 up-classes 与 20"20" 进行比较。这种静默转换可能很好(有用且灵活),但它也可能导致意想不到的、不希望的、and/or 令人惊讶的结果。 (我不喜欢它安静,但方便就是方便。)

如果你想完全清楚你的比较,你也可以测试class。在您的示例中,您显示 20 这是 numeric 而不是技术上的 integer (这将是 20L),但您可以根据自己的喜好调整条件的精度:

filter(data, is.numeric(depth_m) & depth_m == 20)

这仍然会 up-class 20"20",但由于第一部分 is.numeric(.) 失败,因此两者的组合也会失败。意识到该测试的特殊性是绝对的:如果该列确实是字符,那么您将始终得到零行,这可能不是您想要的。相反,如果您只想删除非 20 行,如果它们是 20 和数字,那么也许

filter(data, !is.numeric(depth_m) | depth_m == 20)

这符合 的令人眼花缭乱的逻辑“如果它不是数字,那么它显然不可能是真正的 20,所以保留它......但如果它是数字,请确保绝对是 20"。当然,我们运行这里的前提是不可能列的一部分可以是数字而另一部分不能,所以...也许这就是over-indulging过滤的特殊性。