没有NA的data.frame的最佳子集

Posted

技术标签:

【中文标题】没有NA的data.frame的最佳子集【英文标题】:Best possible subset of data.frame without NA 【发布时间】:2017-08-09 02:18:19 【问题描述】:

我有暗淡的data.frame:160560 x 171。有很多数据,但其中几乎90%是NA。

我愿意使用的算法(我们称之为 ALG)不容忍 data.frame 中的任何 NA。 我的想法是找到这个 data.frame 的最佳子集并在其上使用 ALG。

当我说子集时,我在想什么?包含 n 列 (n

当我说最好的时候,我在想什么?该子集具有尽可能多的行。 F.e.如果我有两个 20 列的子集,第一个有 1152 行,第二个 - 2254,我选择第二个。

问题是简单的组合在那里不起作用,因为 combn(1:171,20) 的结果大于 5*10^25。

R 中是否有任何库可以帮助我处理这个问题?

【问题讨论】:

20 列是您在子集中需要的最小数量吗? 在这种情况下,您只需选择 NA 数量最少的列(检查colSums(is.na(df)) 确实如此,您的标准是最大行数,而不是最大值数。 您要么必须对最小列数施加限制,要么将优化标准更改为跨列的最大非 NA 值数(而不是行数!) 也许遗传算法可以在这里提供帮助?排列优化? 【参考方案1】:

这是使用crossprod 的一种方法。这将为您提供对于给定数量的列具有最大数量的非 NA 行的列。没有办法绕过它,你必须选择一些列才能得到。否则,您将始终选择 NA 最少的单列

首先,让我们为此示例创建一个初始矩阵。此时它必须是一个矩阵。根据需要对您的数据使用as.matrix

set.seed(2)
x <- runif(150)
x[sample(1:150, 15, replace = FALSE)] <- NA
x <- matrix(x,ncol=10)
round(x,1)
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
 [1,]  0.2  0.9  0.0  0.8  0.8  0.8  1.0  0.6  0.0   0.7
 [2,]  0.7  1.0  0.2  1.0  0.9  0.3  0.4  0.9  0.2   0.5
 [3,]  0.6  0.2  0.8  0.3  0.6  0.9  0.4  0.5   NA   0.8
 [4,]  0.2  0.4  0.9  0.5  0.3  0.4  0.6  0.1  0.9   0.2
 [5,]  0.9  0.1  0.5  0.8  0.9  0.6  0.5  0.1  0.2   0.4
 [6,]  0.9  0.7  0.6  0.0  0.4  0.4  0.2  0.0  0.8   0.2
 [7,]   NA  0.4  0.8  0.0  0.4  0.7  0.4  0.7  0.6   0.3
 [8,]  0.8  0.8  0.3  0.7  0.5  0.0  0.1  0.4  0.3   0.6
 [9,]  0.5  0.2  0.7   NA  0.2  0.4  0.1   NA  0.7   0.3
[10,]  0.5   NA  0.2  0.3  0.1  0.2  0.4  0.8  0.3    NA
[11,]  0.6  0.5   NA  0.8  0.3  0.9  0.2  0.8  0.2   0.7
[12,]   NA  0.1   NA  0.8  0.3  1.0  0.4  0.9   NA   0.7
[13,]  0.8   NA  0.1   NA  0.0  0.3  1.0   NA  0.0   0.3
[14,]  0.2  1.0  0.2  0.6  0.2  0.7   NA  1.0   NA   0.5
[15,]  0.4  0.1  0.9  0.7  0.2  0.3  0.3  0.6  0.3   0.3

如您所见,第 5 列和第 6 列没有 NAs

现在,让我们创建一个类似的矩阵,其中 NA 为 0,非 NA 为 1。

is_na_vector<- ifelse(is.na(x),0,1)

之后,让我们计算crossproduct

crossprod_vector <- crossprod(is_na_vector)
colSums(crossprod_vector)
 [1] 119 120 119 120 135 135 127 120 111 127

如您所见,第 5 列和第 6 列的colSums 最高。这意味着,结合其他变量,它们的 NA 数量最少

然后我们使用 colSums 向量来选择一些列。这将对所有列进行排名并首先给出n。这是非 NA 行数最多的三列。在本例中为 14 行。此时可能存在平局,但当您选择 20 列时应该没有问题。

n <- 3
x_df <- as.data.frame(x) #to get meaningful colnames
res <- x_df[,rank(-colSums(crossprod_vector),ties.method ="first")<=n ] #use "-" to get decreasing rank
res
          V5        V6        V7
1  0.7700279 0.7554624 0.9767552
2  0.8869842 0.2880597 0.3970164
3  0.6251217 0.8678447 0.3799989
4  0.2603000 0.4026427 0.5603876
5  0.8590731 0.5726850 0.4638082
6  0.4374880 0.3506426 0.1967768
7  0.3881448 0.6719989 0.4269434
8  0.4615011 0.0250504 0.0930252
9  0.2186752 0.4011010 0.1153091
10 0.0659355 0.1999765 0.4400317
11 0.2757010 0.8565250 0.2009347
12 0.3103811 0.9715154 0.4276391
13 0.0421755 0.3237224 0.9806000
14 0.1846735 0.7331914        NA
15 0.1833732 0.3400682 0.2869739

使用 na.omit 获取非 NA 行:

na.omit(res)
          V5        V6        V7
1  0.7700279 0.7554624 0.9767552
2  0.8869842 0.2880597 0.3970164
3  0.6251217 0.8678447 0.3799989
4  0.2603000 0.4026427 0.5603876
5  0.8590731 0.5726850 0.4638082
6  0.4374880 0.3506426 0.1967768
7  0.3881448 0.6719989 0.4269434
8  0.4615011 0.0250504 0.0930252
9  0.2186752 0.4011010 0.1153091
10 0.0659355 0.1999765 0.4400317
11 0.2757010 0.8565250 0.2009347
12 0.3103811 0.9715154 0.4276391
13 0.0421755 0.3237224 0.9806000
15 0.1833732 0.3400682 0.2869739

您可以通过nrow 看到有多少非 NA 行:

nrow(na.omit(res)) #14

对于n &lt;- 5,我得到 12 个非 NA 行

【讨论】:

以上是关于没有NA的data.frame的最佳子集的主要内容,如果未能解决你的问题,请参考以下文章

子集数据框时选择了未定义的列

子集 R 数据框导致神秘的 NA 行

一个因子的 addNA 之后的子集数据帧

R中的cor()行为在各个向量和data.frame之间有所不同

如何从数据帧的子集中删除值

如何按名称选择列的子集来计算 R 中的行均值? [复制]