如何通过R中可用的公共数值对多列的数据帧进行子集/拆分

时间:2016-01-12 16:20:27

标签: r split dataframe subset

我有一个超过4000列的数据框。并且列显示库存数据并具有缺失值。数据框具有各种缺失值,因为数据框具有目前在证券交易所上市/交易的公司以及过去在证券交易所交易的公司。如果公司A有2000年的收盘价数据,但是公司B可能没有2000年的任何数据,因为公司B在2000年没有交易/上市,因此缺少价值。这使得我的数据帧非常复杂,并且由于缺少数据而难以运行诸如Autoregressive之类的模型。所以,我想根据它们之间的常见缺失值(列)拆分/子集这个数据帧,然后删除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

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

4 个答案:

答案 0 :(得分:2)

这应该适用于你正在做的事情,它会产生一个数据框列表,你可以一次索引到一个数据框:

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]]}

答案 1 :(得分:2)

还有一个解决方案:)

# 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])

答案 2 :(得分:1)

使用data.table包将整个事物转换为data.table。

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

例如dt[!is.na(A) & !is.na(D) & !is.na(E) & !is.na(F), .(A,D,E,F)]应该为您提供第一张表。

您是否可以更明确地制定各种子表的规则?

答案 3 :(得分:1)

首先使用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]) ]