2017-07-21 20 views
-1

我有兩個數據框架,預計是相同的(按PK排序)。
我需要列出不同的行 - 具有任何不同列的任何行。
顯示的最後一個功能完成了這項工作,但耗時太長。
@Gilles提供了一個更好的解決方案,使用apply。這是顯示交替行的修改版本(df1df2)。列出數據幀不同的行 - 性能不佳

良好的性能解決方案(0.1秒!):

compDfOrden=function(df1,df2){ 
    df1=df1[complete.cases(df1),] 
    df2=df2[complete.cases(df2),] 
    df1d=data.frame(); df2d=data.frame() 
    if(nrow(df1)!=nrow(df2)){cat('different lines number'); return() 
    } else linhas=nrow(df1) 
    if(ncol(df1)!=ncol(df2)){cat('different columns number'); return() 
    } else colunas=ncol(df1) 
    different <- apply(df1 != df2, 1, any) 
    difRows=sum(different) 
    if(difRows>0){ 
    df1d=cbind(df='df1',l=1:difRows,df1[different,]) 
    df2d=cbind(df='df2',l=1:difRows,df2[different,]) 
    dfd=rbind(df1d,df2d) 
    dfd=with(dfd,dfd[order(l,df),])[,-2] 
    } else dfd=data.frame() 
    return(dfd) 
} 
    } 
tz1=Sys.time() 
z=compDfOrden(t1,t2) 
Sys.time()-tz1 
Time difference of 0.1000059 secs 
nrow(z)/2 
9303 
nrow(t1) 
9305 
row.names(z)=NULL 
head(z,2) 
    df c1 c2 c3 c4 c5  c6  c7  c8  c9  c10  c11  c12 c13 c14  c15 c16 c17 
1 df1 1390 ALPA4 F 8 1 0.224000 0.206000 0.275000 0.277000 16.09403 -18.9546 20.75508 2.7116 -1.926 0.4254945 10.3 11.08 
2 df2 1390 ALPA4 F 8 1 0.223516 0.205639 0.274514 0.277207 16.10096 -18.9821 20.75508 2.6829 -1.926 0.4254945 10.3 11.08 
    c18 c19  c20  c21 
1 10.61 2.02 6.931000 2.920000 
2 10.61 2.02 6.930612 2.921772 

較差的性能解決方案(2.6分):

compDfOrden=function(df1,df2){ 
    df1d=data.frame() 
    if(nrow(df1)!=nrow(df2)){cat('no. linhas diferentes'); return() 
    } else linhas=nrow(df1) 
    if(ncol(df1)!=ncol(df2)){cat('no. colunas diferentes'); return() 
    } else colunas=ncol(df1) 
    for(x in 1:linhas){ 
    for(y in 1:colunas){ 
     if(df1[x,y]!=df2[x,y]){ 
    #if(!identical(df1[x,],df2[x,])){ 
     df1d=rbind(df1d,cbind(df='df1',df1[x,])) 
     df1d=rbind(df1d,cbind(df='df2',df2[x,])) 
     break()} 
    } 
    } 
    return(df1d) 
} 
t1=Sys.time() 
z=compDfOrden(df1,df2) 
Sys.time()-t1 
Time difference of 2.584698 mins 
nrow(df2) 
9305 

if(!identical(df1[x,],df2[x,])){...更糟糕的是(2.64分鐘)。

+0

爲什麼這個問題negativated? – xm1

+0

我沒有downvote,但不清楚你到底在問什麼。特別是在你編輯之後加入Gilles的答案。而你的問題的標題是非常通用的。 – Uwe

+0

@UweBlock我在詢問性能增益。我會改變標題。吉爾斯的回答是完美的,我改變了功能來融入他的想法。我這樣做,因爲它可以用於搜索相同的其他人。 – xm1

回答

1

這樣稍微改善(快3倍)。然而,我不得不建立一個比你的線條多得多的矩陣來達到幾秒鐘(也許你有很多列和/或功率較小的計算機?)。我對數據的介紹略有不同,但您可以對其進行調整,但這不會改變性能。

# Reproducible example 
df1 <- matrix(rnorm(4000000), ncol = 4) 
colnames(df1) <- LETTERS[1:ncol(df1)] 
rownames(df1) <- 1:nrow(df1) 
df2 <- df1 
df2[2, 3] <- rnorm(1) 
df2[6, 1] <- rnorm(1) 

comp_test <- function(df1, df2) { 
    different <- apply(df1 != df2, 1, any) 
    cbind(df1[different,, drop = FALSE], df2[different,, drop = FALSE]) 
} 

時差和結果:

> comp_test(df1,df2) 
      A   B   C   D   A   B   C   D 
2 0.4769979 -0.2693178 0.750328 1.8281688 0.4769979 -0.2693178 -0.06271077 1.8281688 
6 0.5396275 0.4195784 -1.865591 -0.5488179 0.5456412 0.4195784 -1.86559051 -0.5488179 
> Sys.time()-t1 
Time difference of 1.606129 secs 
> 
> 
> t1=Sys.time() 
> compDfOrden(df1,df2) 
    df     V2 
A df1 0.476997924412505 
B df1 -0.26931778399519 
C df1 0.750328023463562 
D df1 1.82816879962394 
A1 df2 0.476997924412505 
B1 df2 -0.26931778399519 
C1 df2 -0.0627107709133403 
D1 df2 1.82816879962394 
A2 df1 0.539627546788513 
B2 df1 0.419578406226185 
C2 df1 -1.86559050830151 
D2 df1 -0.548817860878508 
A3 df2 0.545641208974783 
B3 df2 0.419578406226185 
C3 df2 -1.86559050830151 
D3 df2 -0.548817860878508 
> Sys.time()-t1 
Time difference of 5.664673 secs 
> 

速度的提高是高,當你有更多的差異:

> df1 <- matrix(rnorm(4000000), ncol = 4) 
> df2 <- df1 
> nb_differences <- 3000 
> df2[sample(1:length(df2), nb_differences)] <- rnorm(nb_differences) 
> 
> 
> t1=Sys.time() 
> res <- comp_test(df1,df2) 
> Sys.time()-t1 
Time difference of 1.127508 secs 
> 
> 
> t1=Sys.time() 
> res <- compDfOrden(df1,df2) 
> Sys.time()-t1 
Time difference of 21.24287 secs 
+0

主要消費是由於差異數量(數據框「寫入」)。幾乎沒有什麼區別,它會下降到秒。我會嘗試'apply'函數並告訴。 – xm1

+0

這似乎不是'CompDfOrden':它給出'df1'和'df2'交替。 – xm1

+0

數據幀有21列,@Gilles – xm1

1

我真的不知道這是你想要的,但看看這個功能是否有幫助。它受到Petr Savicky對R-Help問27.F.2012問題的啓發。

setdiffDF <- function(A, B){ 
    f <- function(A, B) 
     A[!duplicated(rbind(B, A))[nrow(B) + 1:nrow(A)], ] 
    df1_name <- deparse(substitute(df1)) 
    df2_name <- deparse(substitute(df2)) 
    df1 <- f(A, B) 
    df2 <- f(B, A) 
    df1$df <- df1_name 
    df2$df <- df2_name 
    rbind(df1, df2) 
} 

經過測試,但不包含您的數據,因爲您沒有發佈任何內容。

+0

似乎比@ xm1函數慢得多 – Gilles

+0

@Gilles:你說得對,很慢很多。 –

+0

@ xm1:檢出軟件包'prob',函數'setdiff'。 –