我有两个桌子。在一个表(IPTable)中,一个表中有一列包含IP地址(如下所示:“ 10.100.20.13”)。我正在尝试将每个数据与另一个表(SubnetTable)中包含子网地址的列中的数据进行匹配(看起来像这样:“ 10.100.20”,本质上是IP地址的简化版本-第3个之前的所有内容期)。这两个变量似乎都是chr向量。
基本上,原始IP数据如下所示:
IPTable $ IPAddress
10.100.20.13
10.100.20.256
10.100.200.23
101.10.13.43
101.100.200.1
和我正在比较的原始子网数据如下:
SubnetTable $ Subnet
变化
10.100.20
远程子网
10.100.200,101.10.13
未知子网
注意:
有时子网条目在用逗号分隔的字段中包含两个子网
IPAddress字段在组之间的位置不一致(例如-可能存在“ 10.110 .20.13”和“ 101.10 ”。 20.13“)
在不同脚本应用程序中,我能够在foreach循环中简单地将它们作为字符串进行比较。按照这种逻辑,它将遍历子网数据(SubnetTable)中的每个条目,将其与逗号分隔(以说明具有多个子网地址的条目),然后检查是否在“ IP地址”字段中找到匹配项(例如-是在“ 10.100.20.13”中的任意位置找到的“ 10.100.20”)。我使用该字段进行联接/合并。在使用R时,我了解到foreach循环并不是我应该这样做的最有效方法,而在其他应用程序中则需要很长时间,这就是我转向R的部分原因。
我没有看到针对这种类型的数据执行相同操作的方法(我已经完成了合并和联接,但是我没有看到一种方法,而没有获得两个足够相似的变量来链接两张桌子)。
过去,我已经能够使用sqldf,charindex和leftstr之类的R方法来查找特定字符“”。并把所有东西都拉到前面,但是这里的困难是要那样做,我需要寻找“”期间的第三次出现。而不是第一个。 我没有看到这样的方法,但是如果有一种方法,那可能是最好的。
我的下一个尝试是在IP地址上使用strsplit和sapply,其想法是仅重新组装前三个部分以创建要匹配的子网(在新列/变量中)。看起来像这样:
IPClassC <- sapply(strsplit(Encrypt_Remaining5$IPAddress, "[.]"), `[`)
这给出了一个“大列表”,使数据看起来像这样:
chr [1:4]“ 10”“ 100”“ 20” 13“
但是,当尝试将其放回原位时,我也会丢失八位位组之间的时间间隔。示例代码:
paste(c(IPClassC[[1]][1:3]), sep ="[.]", collapse = "")
这将产生如下内容:
“ 1010020”
最后我有两个问题:
1)是否有一种方法可以做我之前做的简单比较(本质上是将表1的子网变量合并到表2的IP地址的“大部分”,这种合并基于第三段之前的所有内容)。 ”),而不必将其拆分并重新组合IPAddress字段?
2)如果不是,我是否在尝试拆分然后重新组装的正确轨道上?如果是这样,我在进行重组时出了什么问题?或者有更简便/更好的方法吗?
谢谢,让我知道您还需要什么。
答案 0 :(得分:1)
我认为您实际上要问的是如何将这两个表结合在一起,对吗?如果是这样,我会这样:
library(tidyr)
suppressPackageStartupMessages(library(dplyr))
IPTable <-
data.frame(
IPAddress =
c(
"10.100.20.13",
"10.100.20.256",
"10.100.200.23",
"101.10.13.43",
"101.100.200.1"
),
stringsAsFactors = FALSE
)
我不确定您的SubnetTable是否真的像这样,即将子网地址与其他文本混合在一起吗?无论如何,此解决方案实际上会忽略其他文本。
SubnetTable <-
data.frame(
subnet_id = 1:5,
Subnet =
c(
"Varies",
"10.100.20",
"Remote Subnet",
"10.100.200, 101.10.13",
"Unknown Subnet"
),
stringsAsFactors = FALSE
)
首先,我们将多个子网分成多行。请注意,这假设SubnetTable$Subnet
向量仅包含一个", "
来分隔两个子网。即没有像这样的"Unknown, Subnet"
字符串,否则它们也将分为两行。
SubnetTable_tidy <- tidyr::separate_rows(SubnetTable, Subnet, sep = ", ")
SubnetTable_tidy
#> subnet_id Subnet
#> 1 1 Varies
#> 2 2 10.100.20
#> 3 3 Remote Subnet
#> 4 4 10.100.200
#> 5 4 101.10.13
#> 6 5 Unknown Subnet
接下来,我们通过替换/删除点(Subnet
),然后是一到三个数字(\\.
),然后是字符串的结尾({{1}),来提取\\d{1,3}
})来自$
。
IPTable$IPAddress
现在我们可以连接两个表了。
IPTable$Subnet <- gsub("\\.\\d{1,3}$", "", IPTable$IPAddress)
IPTable
#> IPAddress Subnet
#> 1 10.100.20.13 10.100.20
#> 2 10.100.20.256 10.100.20
#> 3 10.100.200.23 10.100.200
#> 4 101.10.13.43 101.10.13
#> 5 101.100.200.1 101.100.200
答案 1 :(得分:0)
unlist(strsplit(SubnetTable$Subnet,split=",")) %in%
gsub("^(\\d{2,3}.\\d{2,3}.\\d{2,3}).*$","\\1",IPTable$IPAddress)
这将为您提供一个logical
类的向量,该向量与子网中的每个项目都匹配TRUE / FALSE(对其中包含逗号的项目给出多个响应)。或者,您可以翻转两侧以获取每个IPAddress的逻辑列表,并告诉您该IP地址是否存在于子网列表中。
这是您要找的吗?
您也可以使用charmatch
获得类似的结果:
sapply(strsplit(SubnetTable$Subnet, split=","), charmatch, IPTable$IPAddress)
这将为您的示例数据提供以下结果:
[[1]]
[1] NA
[[2]]
[1] 0
[[3]]
[1] NA
[[4]]
[1] 3 NA
[[5]]
[1] NA
请注意,只有一个匹配项时,您会得到它的索引,但是如果有多个匹配项,则值为0
。
最后,翻转此按钮将为您提供IP地址与以下地址匹配的子网中的索引列表:
sapply(gsub("^(\\d{2,3}.\\d{2,3}.\\d{2,3}).*$","\\1",IPTable$IPAddress), charmatch, SubnetTable$Subnet)
导致:
10.100.20 10.100.20 10.100.200 101.10.13 101.100.200
2 2 4 NA NA