如何 subset/split 由 R 中可用的常用值数组成的多列数据框

How to subset/split a dataframe of multiple columns by common number of values available in R

我有一个包含 4000 多列的数据框。并且列显示股票数据并具有缺失值。数据框有各种缺失值,因为数据框有目前在证券交易所 listed/trading 的公司以及过去在证券交易所交易的公司。如果 A 公司有 2000 年的收盘价数据,但 B 公司可能没有 2000 年的任何数据,因为 B 公司在 2000 年没有 trading/listed,因此缺少值。这使得我的数据框变得非常复杂,并且由于缺少数据而难以 运行 模型(例如自回归)。所以,我想 split/subset 这个数据框基于它们(列)之间的共同缺失值,然后删除 NA 和 运行 模型。我将数据和所需的输出说明如下

df
DATE         A      B   C        D      E   F   G   H
31/12/1999  79.5    NA  NA      36.7    3   6   NA  NA
03/01/2000  79.5    NA  NA      36.7    3   6   NA  NA
04/01/2000  79.5    NA  325     36.7    3   6   961 3081.9
05/01/2000  79.5    NA  322.5   38.8    3   6   945 2524.7
06/01/2000  79.5    NA  327.5   20.3    3   6   952 3272.3
07/01/2000  79.5    NA  327.5   15.6    3   6   941 2102.9
10/01/2000  79.5    7   327.5   5.4     3   6   946 2901.5
11/01/2000  79.5    7   327.5   15      3   6   888 9442.5
12/01/2000  79.5    7   331.5   9.3     3   6   870 7865.8
13/01/2000  79.5    7   334     29.1    3   6   853 7742.1

我想要如下数据框:

d1<-df
DATE         A       D      E   F
31/12/1999  79.5    36.7    3   6
03/01/2000  79.5    36.7    3   6
04/01/2000  79.5    36.7    3   6
05/01/2000  79.5    38.8    3   6
06/01/2000  79.5    20.3    3   6
07/01/2000  79.5    15.6    3   6
10/01/2000  79.5    5.4     3   6
11/01/2000  79.5    15      3   6
12/01/2000  79.5    9.3     3   6
13/01/2000  79.5    29.1    3   6
df2<- df
DATE         C      G   H
31/12/1999  NA      NA  NA
03/01/2000  NA      NA  NA
04/01/2000  325     961 3081.9
05/01/2000  322.5   945 2524.7
06/01/2000  327.5   952 3272.3
07/01/2000  327.5   941 2102.9
10/01/2000  327.5   946 2901.5
11/01/2000  327.5   888 9442.5
12/01/2000  331.5   870 7865.8
13/01/2000  334     853 7742.1

df3 <- df 
DATE    B
31/12/1999  NA
03/01/2000  NA
04/01/2000  NA
05/01/2000  NA
06/01/2000  NA
07/01/2000  NA
10/01/2000  7
11/01/2000  7
12/01/2000  7
13/01/2000  7

非常感谢你在这方面的帮助。

使用 data.table 包将整个东西变成 data.table。

然后使用 data.table[] 的第一个参数对您的列和行进行子集化。

例如 dt[!is.na(A) & !is.na(D) & !is.na(E) & !is.na(F), .(A,D,E,F)] 应该给你第一个 table。

您能否更明确地说明制作各种子 table 的规则?

首先使用apply计算每列中的NA数量:

gr <- apply(df ,2 ,function(x) sum(is.na(x)))
gr
DATE    A    B    C    D    E    F    G    H 
   0    0    6    2    0    0    0    2    2 

现在您可以对 data.frame 进行子集化并指定阈值 你想要的输出。

df[, c("DATE",colnames(df)[gr==0]) ]
df[, c("DATE",colnames(df)[gr>0 & gr<=5 ]) ]
df[, c("DATE",colnames(df)[gr>5]) ]

这应该适用于您正在做的事情,它会生成一个数据帧列表,您可以一次将其索引到一个数据帧中:

c <- sapply(df[, 2:ncol(df)], function(x) sum(!is.na(x)))
x <- sapply(unique(c), function(x) which(x == c))
dfList <- list(); for(i in 1:length(x)) {dfList[[i]] <- df[, c(1, as.numeric(x[[i]]) + 1)]}

输出如下:

dfList
[[1]]
         DATE    A    D E F
1  31/12/1999 79.5 36.7 3 6
2  03/01/2000 79.5 36.7 3 6
3  04/01/2000 79.5 36.7 3 6
4  05/01/2000 79.5 38.8 3 6
5  06/01/2000 79.5 20.3 3 6
6  07/01/2000 79.5 15.6 3 6
7  10/01/2000 79.5  5.4 3 6
8  11/01/2000 79.5 15.0 3 6
9  12/01/2000 79.5  9.3 3 6
10 13/01/2000 79.5 29.1 3 6

[[2]]
         DATE  B
1  31/12/1999 NA
2  03/01/2000 NA
3  04/01/2000 NA
4  05/01/2000 NA
5  06/01/2000 NA
6  07/01/2000 NA
7  10/01/2000  7
8  11/01/2000  7
9  12/01/2000  7
10 13/01/2000  7

[[3]]
         DATE     C   G      H
1  31/12/1999    NA  NA     NA
2  03/01/2000    NA  NA     NA
3  04/01/2000 325.0 961 3081.9
4  05/01/2000 322.5 945 2524.7
5  06/01/2000 327.5 952 3272.3
6  07/01/2000 327.5 941 2102.9
7  10/01/2000 327.5 946 2901.5
8  11/01/2000 327.5 888 9442.5
9  12/01/2000 331.5 870 7865.8
10 13/01/2000 334.0 853 7742.1

要从上面数据框列表中的每个数据框中只检索完整的案例,您可以这样做:

dfList <- sapply(dfList, function(x) x[complete.cases(x), ])

结果输出将是本例中三个数据框的以下列表:

[[1]]
         DATE    A    D E F
1  31/12/1999 79.5 36.7 3 6
2  03/01/2000 79.5 36.7 3 6
3  04/01/2000 79.5 36.7 3 6
4  05/01/2000 79.5 38.8 3 6
5  06/01/2000 79.5 20.3 3 6
6  07/01/2000 79.5 15.6 3 6
7  10/01/2000 79.5  5.4 3 6
8  11/01/2000 79.5 15.0 3 6
9  12/01/2000 79.5  9.3 3 6
10 13/01/2000 79.5 29.1 3 6

[[2]]
         DATE B
7  10/01/2000 7
8  11/01/2000 7
9  12/01/2000 7
10 13/01/2000 7

[[3]]
         DATE     C   G      H
3  04/01/2000 325.0 961 3081.9
4  05/01/2000 322.5 945 2524.7
5  06/01/2000 327.5 952 3272.3
6  07/01/2000 327.5 941 2102.9
7  10/01/2000 327.5 946 2901.5
8  11/01/2000 327.5 888 9442.5
9  12/01/2000 331.5 870 7865.8
10 13/01/2000 334.0 853 7742.1

您可以按如下方式访问每个数据帧:

for (i in 1:lenght(dfList)) {dfList[[i]]}

还有一个解决方案:)

# always give reproducible example
df <- data.frame(A=LETTERS[1:10],
                 B=c(rep(NA, 8), 1:2),
                 C=c(rep(NA, 6), 1:4),
                 D=c(rep(NA, 6), 5:8))

# get indices of NAs in each column
l <- lapply(df, function(i) which(is.na(i)))

# create factors to group columns with identical NA indices
# this is stupid and could be inefficient for data.frames with lots of NA values in columns
f <- factor(sapply(l, paste, collapse=","))

# split initial data.frame on a list of data.frames
list_of_dfs <- lapply(levels(f), function(fl) df[, which(f == fl), drop = FALSE])