按R中的条件从data.frame列出(几乎)相等的列

时间:2011-08-16 17:22:08

标签: r filter dataframe subset

首先没有细节

data.frame就像那样:

  val1 val2 val3 val4 val5
1  1.1    2  1.1  2.1  4.2
2  5.7    5  5.6  4.9  9.9
3  3.1    3  3.2  2.9  5.9
4  9.6    1  9.5  1.0  2.0

并希望获得(几乎)相等的行。期望的结果将是

[1] "val1" "val2" "val5"

因为列val3几乎等于val1val4几乎等于val2val5不同。

详细信息:

  • “几乎”平等意味着什么(只是下面列出的选项之一):
    • 值的绝对差值小于固定数量(上述样本为0.2)
    • 值的相对差异小于固定数量(样本约为11%)
    • 其他有意义的指标; - )
  • 线性相关列的列表会更好(但我认为这更复杂)(这意味着val5也是val2和{{val4组成的组的一部分1}}因为它大约是价值的两倍)
  • 它不是很快,O(n^2)会好的。 (我的框架只有大约12行和300列)
  • 如果不可能,那么完全相等的列的列表也会以某种方式工作。然后我会在
  • 之前应用round()函数

2 个答案:

答案 0 :(得分:3)

复制您的数据:

structure(list(val1 = c(1.1, 5.7, 3.1, 9.6), val2 = c(2L, 5L, 
3L, 1L), val3 = c(1.1, 5.6, 3.2, 9.5), val4 = c(2.1, 4.9, 2.9, 
1), val5 = c(4.2, 9.9, 5.9, 2)), .Names = c("val1", "val2", "val3", 
"val4", "val5"), class = "data.frame", row.names = c("1", "2", 
"3", "4"))
x
  val1 val2 val3 val4 val5
1  1.1    2  1.1  2.1  4.2
2  5.7    5  5.6  4.9  9.9
3  3.1    3  3.2  2.9  5.9
4  9.6    1  9.5  1.0  2.0

创建一个功能。该机制是围绕基本R函数duplicated,它具有一个也可以处理列的数组方法,这与仅处理行的data.frames的方法不同。另外,我带你到你的话并围绕每一列,但你可以指定位数作为参数。

not_duplicated <- function(x, round_digits, margin=2){
  x2 <- apply(x, margin, round, round_digits)  
  colnames(x)[!duplicated(x2, MARGIN=margin)]
}

结果如您所指定:

x <- as.matrix(x)
not_duplicated(x, 0)
[1] "val1" "val2" "val5"

答案 1 :(得分:3)

如何选择哪些行相等,定义不明确;例如,你可以有三列,其中A和B是“相等的”,B和C是“相等”但A和C不是。该怎么办?一种方法可能是使用层次聚类,可能是这样的:

使用Andrie的答案中的数据,首先将其转置并将其转换为矩阵;我还会将每一行(什么是列)标准化,作为寻找线性组合的开始;这将对彼此完全相同但不是更复杂组合的行进行分组。

d <- t(as.matrix(d))
s <- rowSums(d)
ds <- sweep(d, 1, s, `/`)

我们现在制作一棵树,并为了兴趣,绘制它。这使用默认距离函数(Euclidean),但其他函数是可能的。

tree <- hclust(dist(ds))
plot(tree)

plot of tree from hclust

然后我们选择将树切割成组的位置(这是您选择两者必须“相等”的位置);我将它与值的总和一起输出,以查看是否有任何值的倍数。

> grp <- cutree(tree, h=0.1)
> cbind(grp, s)

     grp    s
val1   1 19.5
val2   2 11.0
val3   1 19.4
val4   2 10.9
val5   2 22.0