R 如何识别作为数据集中其他列总和的列

R 如何识别作为数据集中其他列总和的列,r,matrix,linear-algebra,R,Matrix,Linear Algebra,我想写一个函数(最好是R语言,但也欢迎其他语言),它可以识别数据集中列之间的关系(仅限于添加/删除)。这种方法的一个实际应用是在大型多列金融数据集上运行它,其中一些列是其他列的小计,并识别此类小计 理想情况下,我希望考虑小的差异-例如,考虑到四舍五入问题,导致列的总和不完全为100% 我发现了以下内容,其中包括一个涉及矩阵和秩的解决方案,但我不确定是否有任何方法可以将处理舍入问题引起的数据噪声的能力结合起来 例如: d = data.frame(a=c(10.12, 20.02, 30.08,

我想写一个函数(最好是R语言,但也欢迎其他语言),它可以识别数据集中列之间的关系(仅限于添加/删除)。这种方法的一个实际应用是在大型多列金融数据集上运行它,其中一些列是其他列的小计,并识别此类小计

理想情况下,我希望考虑小的差异-例如,考虑到四舍五入问题,导致列的总和不完全为100%

我发现了以下内容,其中包括一个涉及矩阵和秩的解决方案,但我不确定是否有任何方法可以将处理舍入问题引起的数据噪声的能力结合起来

例如:

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)
在我把噪声引入方程之前,这个连环问题的解是有效的。e、 g.
d$d[[4]]=d$d[[4]]+0.01
-那么它就根本不起作用了。因此,我的问题是:

  • 是否有其他方法来确定两者之间的关系 列(特别是当它们被限制为简单 加法/减法)
  • 是否有任何方法能够解决问题 不完善的数据质量问题还是我需要构建一些额外的 它的功能(例如,在通过等级识别算法运行数据之前对数据进行四舍五入)

  • 如果您只需要检查任何列是否是其他两列之和的结果,那么这里有一个想法是可行的。它还允许您添加噪波。我们基本上首先通过添加原始数据集的所有组合来创建数据帧。然后,我们用创建的数据帧减去数据集的每一列。如果所有值均为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"
    
    如果我们想让它更灵活,那么我们可以添加另一个参数来获取(列的)组合数,即


    f1如果只允许对连续列进行求和,并且只允许对以前的值进行求和,那么对于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;
                }
            }
        }
    }
    

    这可以修改为允许连续列和任意数量的总和列,同时保持可处理性(假设总和列的数量保持较低)。这种修改并不完全是微不足道的,留给读者作为练习。

    部分答案是使用
    lm
    。这至少应该返回其他变量的线性组合,如NA
    summary(lm(rnorm(4)~,data=d))
    。@lmo如果我错了,请纠正我,但lm需要知道因变量/自变量-在这种情况下,我不知道什么是相依的,什么是独立的。这在理论上是正确的,也许我滥用了这个函数,但请注意,我添加了一个标准正态分布的随机样本作为因变量。现在,协变量(“独立”变量)根据其共线性进行评估。如果太近,则
    lm
    返回NA。我相信(基于之前的SO帖子)协变量是按更大的“独立性”顺序选择的,因此在回归结果中最共线的变量被忽略。如果你添加一列1作为第一列,链接的解决方案将能够在你做d$d[[4]]此外,您可能希望在问题中包含一个示例,说明我的链接解决方案不起作用。如果我对您提供的输入使用
    linfinder(as.matrix(d))
    ,我会得到您想要的输出。谢谢。不幸的是,实际案例几乎总是涉及两列以上。我认为这种方法的可扩展性不强,无法支持至少10-20列?如果你的意思是1列可能是10或20列之和的乘积,那么不,这是行不通的。您必须将
    combn
    参数从2更改为任意数量的列want@Aurimas我对函数进行了编辑,使其更加灵活,尽管我怀疑它在效率方面不会表现得很好感谢-将尝试使用它和一些真实的示例来了解它是如何工作的感谢-在真实的数据集中“连续性”限制将意味着无法确定“二阶”小计(即a+b=c、d+e=f和g=c+f),但我看到了这可能仍然有用的地方!这就是包含总和列有帮助的地方。如果允许非连续总和列与连续非总和列一起使用,则还将包含任何二阶总计。
    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"
    
    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