R中的两个数据帧都包含IP地址字段。在每个数据帧中,这些字段是“因子”。用户打算基于这些IP地址以及一些其他字段合并两个数据帧。问题是每个数据帧都有不同的IP格式:
Dataframe A examples: 123.456.789.123, 123.012.001.123, 987.001.010.100
Dataframe B中的相同IP格式为:
Dataframe B examples: 123.456.789.123, 123.12.1.123, 987.1.10.100
从A中删除前导零或将它们添加到B以便在合并中使用它们的最佳(最有效)方法是什么?该操作将在数百万条记录上执行,因此“最有效”是考虑到计算时间(需要相对较快)。
答案 0 :(得分:6)
您可以使用sprintf
格式化各个部分。例如,对于给定的数值a
:
b <- sprintf("%.3d", a)
因此,对于IP地址,请尝试以下功能:
printPadded <- function(x){
retStr = paste(sprintf("%.3d",unlist(lapply(strsplit(x,"\\.", perl = TRUE), as.numeric))), collapse = ".")
return(retStr)
}
以下是两个例子:
> printPadded("1.2.3.4")
[1] "001.002.003.004"
> lapply(c("1.2.3.4","5.67.100.9"), printPadded)
[[1]]
[1] "001.002.003.004"
[[2]]
[1] "005.067.100.009"
要向另一个方向前进,我们可以使用gsub
函数中的分割值printPadded
删除前导零。对于我的钱,我建议不要删除前导零。没有必要删除零(或填充它们),但固定宽度格式更容易阅读和排序(即对于那些排序函数的词典)。
更新1:只是速度建议:如果您正在处理大量IP地址,并且真的想加快速度,那么您可能会考虑多核方法,例如mclapply
。 plyr
包也很有用,ddply()
作为一个选项。这些还通过.parallel = TRUE
支持并行后端。尽管如此,即使在单核上,几百万个IP地址也不会花费很长时间。
答案 1 :(得分:2)
另一种方式是这样的:
my @ipparts = split(/\./, $ip);
for my $ii (0..$#ipparts)
{
$ipparts[$ii] = $ipparts[$ii]+0;
}
$ip = join(".", @ipparts);
比sprintf需要的很多分歧更好。