2011-11-17 84 views
4

R中的兩個數據幀均包含用於IP地址的字段。在每個數據框中,這些字段都是「因素」。用戶打算根據這些IP地址以及其他一些字段合併兩個數據幀。問題是,每個數據幀具有的IP地址不同的格式:如何有效地刪除(或添加)R中IP地址的前導零?

Dataframe A examples: 123.456.789.123, 123.012.001.123, 987.001.010.100 

在數據幀B中的相同的IP地址將被格式化爲:

Dataframe B examples: 123.456.789.123, 123.12.1.123, 987.1.10.100 

什麼是最好的(最有效)的方法是刪除來自A的前導零或將它們添加到B以便它們可以用於合併?該操作將在數百萬條記錄上執行,因此'最高效'考慮到計算時間(需要相對較快)。

回答

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" 

要走另一個方向,我們可以使用gsubprintPadded函數中的拆分值刪除前導零。對於我的錢,我建議不要刪除前導零。沒有必要去除零(或填充它們),但固定寬度格式更易於閱讀和排序(即對於那些按字典排序的排序功能)。


更新1:僅有速度的建議:如果你正在處理大量的IP地址,真想加快這,你可能看多方法,如mclapplyplyr包也是有用的,ddply()作爲一個選項。這些也支持並行後端,通過.parallel = TRUE。儘管如此,即使在單個內核上,幾百萬個IP地址也不應該花很長時間。

+0

哇,感謝您的快速響應。我得到一個錯誤 **在strsplit(x,「\\。」,perl = TRUE)中出錯:非字符參數** 我是否需要運行as.character,因爲它們當前是因子級別? – bnjmn

+0

我運行** lapply(as.character(data $ IP),printPadded)**成功。謝謝。等待幾個小時才能接受答案。 – bnjmn

+0

@本傑明啊,你應該小心一些因素。這些可以將所有東西都挖掘出來,因爲有時它們看起來像字符向量,但最終可能會被視爲整數。如果你加載數據,比如說'read.csv()',尋找'stringsAsFactors = FALSE'選項。或者,您可以在您的選項中進行設置 - 查看'?options'。 FWIW,我從沒有受益於加載字符串作爲因素 - 我只在需要時進行顯式因子轉換(例如在某些類型的模型中) – Iterator

2

另一種方法是這樣的:

my @ipparts = split(/\./, $ip); 
for my $ii (0..$#ipparts) 
{ 
    $ipparts[$ii] = $ipparts[$ii]+0; 
} 
$ip = join(".", @ipparts); 

比一大堆師那的sprintf需要更好。