2017-04-24 74 views
3

我想寫一個函數(最好是R,但歡迎使用其他語言),它將識別列中的列之間的關係(限於添加/替換)數據集。這種實際應用將在大型多列金融數據集上運行,其中一些列是其他列的小計 - 並標識這些小計。如何識別數據集中其他列的總和列

理想情況下,我想允許小的差異 - 例如,以允許四捨五入的問題導致列不完全增加100%。

我發現了以下question其中包括涉及矩陣和等級的解決方案,但我不確定是否有任何方法可以將處理因舍入問題而引起的數據中的噪音處理。

作爲一個例子:

d = data.frame(a=c(10.12, 20.02, 30.08, 20.19), b=c(12.12, 20.45, 20.52, 16.72), c=c(11, 123.25, 20.67, 20.78)) 
d$d = d$a + d$b 
d$e = d$d + d$c 
> d 
     a  b  c  d  e 
1 10.12 12.12 11.00 22.24 33.24 
2 20.02 20.45 123.25 40.47 163.72 
3 30.08 20.52 20.67 50.60 71.27 
4 20.19 16.72 20.78 36.91 57.69 

magic_function(d) 
[1] "d$d = d$a + d$b" 
[2] "d$e = d$d + d$c" # or "d$e = d$a + d$b + d$c" (first option preferred) 

在鏈接的問題的解決方案工作良好,直到我噪聲引入方程。例如d$d[[4]] = d$d[[4]] + 0.01 - 那麼它不再起作用。因此,我的問題是:

  1. 是否有任何其他的方法來 列(特別是如果他們被限制在簡單 加法/減法)
  2. 之間確定關係是任何能夠解決 不完善的數據的方法質量問題還是需要爲其構建一些額外的功能(例如,在通過等級識別算法運行數據之前對數據進行四捨五入)。
+0

部分答案是使用'lm'。這應該至少返回其他線性組合的變量,例如NA'summary(lm(rnorm(4)〜。,data = d))'。 – lmo

+0

@lmo糾正我,如果我錯了,但lm需要知道依賴/自變量 - 在這種情況下,我不知道什麼是依賴和什麼是獨立.. – Aurimas

+0

這在理論上是真的,也許我是濫用函數,但注意到我添加了一個隨機樣本作爲因變量從標準正態分佈。現在,協變量(「獨立」變量)被評估爲它們的共線性。如果太接近,那麼'lm'返回一個NA。我相信(根據之前的SO帖子)協變量是按照更大的「獨立性」來選擇的,因此那些最共線的那些被排除在迴歸結果中。 – lmo

回答

0

這裏有一個想法,如果你只需要檢查任何一列是否是任何兩個其他人的總和的結果,那麼這個想法就行得通。它也可以讓你增加噪音。我們首先通過添加原始數據集的所有組合創建一個數據框。然後我們用創建的數據幀減去每一列數據集。如果所有值均爲0,則表示它們匹配。通過使用colSums(i < 0.01) == nrow(i)),我們可以添加所需的噪音。

d2 <- setNames(data.frame(combn(1:ncol(d), 2, function(i) rowSums(d[i]))), 
       combn(names(d), 2, function(j)paste(j, collapse = ' + '))) 

l1 <- lapply(d, function(i) sapply(d2, function(j) Map(function(x, y)abs(x - y), i, j))) 

lapply(l1, function(i) names(which(colSums(i < 0.01) == nrow(i)))) 

#$a 
#character(0) 

#$b 
#character(0) 

#$c 
#character(0) 

#$d 
#[1] "a + b" 

#$e 
#[1] "c + d" 

或使其與noise作爲輸入參數的函數,

f1 <- function(df, noise){ 
    d2 <- setNames(data.frame(combn(1:ncol(df), 2, function(i) rowSums(df[i]))), 
       combn(names(df), 2, function(j)paste(j, collapse = ' + '))) 
    l1 <- lapply(df, function(i) sapply(d2, function(j) 
         Map(function(x, y)abs(x - y), i, j))) 
    Filter(length, lapply(l1, function(i) 
       names(which(colSums(i < noise) == nrow(i))))) 
} 

f1(d, 0.01) 
#$d 
#[1] "a + b" 

#$e 
#[1] "c + d" 

如果我們想讓它更靈活,那麼我們可以添加其他參數採取組合數(列)即

f1 <- function(df, n, noise){ 
    d2 <- setNames(data.frame(combn(1:ncol(df), n, function(i) rowSums(df[i]))), 
       combn(names(df), n, function(j)paste(j, collapse = ' + '))) 
    l1 <- lapply(df, function(i) sapply(d2, function(j) 
         Map(function(x, y)abs(x - y), i, j))) 
    Filter(length, lapply(l1, function(i) 
       names(which(colSums(i < noise) == nrow(i))))) 
} 

sapply(2:3, function(i) f1(d, i, 0.01)) 
#[[1]] 
#[[1]]$d 
#[1] "a + b" 

#[[1]]$e 
#[1] "c + d" 

#[[2]] 
#[[2]]$e 
#[1] "a + b + c" 
+0

謝謝。不幸的是,實際案例幾乎總是涉及2列以上。我認爲這種方法不是可以擴展到至少支持10-20列的嗎? – Aurimas

+0

如果你的意思是1列可能是10或20個人的總和的乘積,那麼不是,這是行不通的。您必須將'combn'參數從2更改爲您想要的任意數量的列 – Sotos

+0

@Aurimas我編輯了該函數以使其更靈活,但我懷疑它在效率方面效果不佳。 – Sotos

0

如果允許的款項僅是連續列,併爲以前只值,計算EFF因此對於10-20列可能是易於處理的。此過程檢查是否列等於先前連續列的總和,具有一定的餘量誤差:

d <- data.frame(a=c(10.12, 20.02, 30.08, 20.19), 
       b=c(12.12, 20.45, 20.52, 16.72), 
       c=c(11, 123.25, 20.67, 20.78)); 
d$d <- round(d$a + d$b + runif(4,0,0.04),2); 
d$e <- round(d$d + d$c + runif(4,0,0.04),2); 

## Assumptions: 
## * sum columns relate to previous values only 
## * sum columns relate to consecutive columns 

sumColumns <- NULL; 
allowedError <- 0.05; 
for(col in 3:ncol(d)){ 
    for(subStart in 1:(col-2)){ 
     for(subEnd in (subStart+1):(col-1)){ 
      if(all(abs(d[,col] - rowSums(d[,subStart:subEnd, drop=FALSE])) < 
        allowedError)){ 
       cat(sprintf("Column %d is a sum of columns %d-%d\n", 
          col, subStart, subEnd)); 
       sumColumns[col] <- TRUE; 
      } 
     } 
    } 
} 

輸出:

Column 4 is a sum of columns 1-2 
Column 5 is a sum of columns 3-4 

這可以被修改,以便允許連續列一起與任意數量的總和列同時保持易處理性(假設總列數保持較低)。這種修改不是微不足道的,而是留給讀者作爲練習。

+0

謝謝 - 在真實的數據集中,「連續性」限制將意味着「二階」小計不會被識別(即其中a + b = c,d + e = f,並且g = c + f),但是我看到這可能仍然有用! – Aurimas

+1

這就是包含和列有用的地方。如果允許非連續的總和列與連續的非總和列一起,則任何二階總計也將包括在內。 – gringer

相關問題