簡體   English   中英

在R中對具有相同缺失值模式的列進行分組

[英]Grouping columns with same missing value patterns in R

讓我有這樣一個缺失值的數據幀(df)(NA)

DF:

head1    head2  head3   head4  head5
-----    -----  -----   -----  -----
65       25     12      65     76
78       5      NA      12     NA
NA       NA     12      5      51
76       32     6       94     11
67       32     NA      1      NA

我想創建一個列表(list1),每個元素由具有相同NA模式的數據幀組成。

對於這個例子:

  • list1 [1]必須包含一個數據框(df1),列df $ head1和df $ head2
  • list1 [2]必須包含一個數據框(df2),列df $ head3和df $ head5
  • list1 [3]必須由列df $ head4的數據框(df3)組成

如何使用R創建這樣的列表? 我會很高興得到任何幫助。 非常感謝。

@akrun,我意識到你的代碼適用於NA不是每列常見的數據幀。 但不適用於以下數據框架。

df1<-data.frame(head1=c(65,78,NA,76,67),
                head2=c(25,5,NA,32,32),
                head3=c(12,12,NA,6,NA),
                head4=c(65,12,5,94,1),
                head5=c(76,NA,51,11,NA)
)



i1 <- which(is.na(df1), arr.ind=TRUE)
l1 <- unique(split(i1[,2], i1[,1]))
i2 <- c(l1, setdiff(seq_along(df1), unlist(l1)))
l2 <- lapply(i2, function(i) df1[i]) 
l2[order(sapply(l2, function(x) colnames(x)[1]))] 

結果是:

[[1]]
  head1 head2 head3
1    65    25    12
2    78     5    12
3    NA    NA    NA
4    76    32     6
5    67    32    NA

[[2]]
  head3 head5
1    12    76
2    12    NA
3    NA    51
4     6    11
5    NA    NA

[[3]]
  head4
1    65
2    12
3     5
4    94
5     1

[[4]]
  head5
1    76
2    NA
3    51
4    11
5    NA

我們得到NA元素的行/列索引which並指定arr.ind=TRUE 我們split “col” split為“row”,獲取索引的unique元素,如果缺少某些列,即沒有NA值,我們可以將( c )連接到list的末尾。 然后,通過循環遍歷listlapply(i2,.. ))使用索引對數據集進行subset集化,並且我們可以order每個list元素中的第一列名稱對輸出list ('l2')進行list

i1 <- which(is.na(df1), arr.ind=TRUE)
l1 <- unique(split(i1[,2], i1[,1]))
i2 <- c(l1, setdiff(seq_along(df1), unlist(l1)))
l2 <- lapply(i2, function(i) df1[i]) 
l2[order(sapply(l2, function(x) colnames(x)[1]))]
#[[1]]
# head1 head2
#1    65    25
#2    78     5
#3    NA    NA
#4    76    32
#5    67    32

#[[2]]
#  head3 head5
#1    12    76
#2    NA    NA
#3    12    51
#4     6    11
#5    NA    NA

#[[3]]
#  head4
#1    65
#2    12
#3     5
#4    94
#5     1

使用每列中的NA值索引,可以將每列映射到“字符”值:

map = sapply(df1, function(X) paste(which(is.na(X)), collapse = ";"))
map
#head1 head2 head3 head4 head5 
#  "3"   "3" "3;5"    "" "2;5"

然后,相應地split列:

split.default(df1, match(map, unique(map)))
#> str(.Last.value)
#List of 4
# $ 1:'data.frame':      5 obs. of  2 variables:
#  ..$ head1: num [1:5] 65 78 NA 76 67
#  ..$ head2: num [1:5] 25 5 NA 32 32
# $ 2:'data.frame':      5 obs. of  1 variable:
#  ..$ head3: num [1:5] 12 12 NA 6 NA
# $ 3:'data.frame':      5 obs. of  1 variable:
#  ..$ head4: num [1:5] 65 12 5 94 1
# $ 4:'data.frame':      5 obs. of  1 variable:
#  ..$ head5: num [1:5] 76 NA 51 11 NA

對於實際大小的數據,性能似乎是可以容忍的:

set.seed(666)
DF = as.data.frame(matrix(sample(c(NA, 1:10), 115000 * 100, TRUE), 115000, 100))
DF = DF[, sample(ncol(DF), 140, TRUE)]

system.time({
    map = sapply(DF, function(X) paste(which(is.na(X)), collapse = ";"))  
    split.default(DF, match(map, unique(map)))
})
#   user  system elapsed 
#   1.64    0.00    1.67

......除非你在每列中有~60% NA

set.seed(911)
DF2 = as.data.frame(replicate(100, sample(c(NA, 1:2), 115000, TRUE, c(0.6, 0.2, 0.2)), simplify = FALSE))
DF2 = DF2[, sample(ncol(DF2), 140, TRUE)]

system.time({
    map = sapply(DF2, function(X) paste(which(is.na(X)), collapse = ";"))  
    split.default(DF2, match(map, unique(map)))
})
#   user  system elapsed 
#   8.70    0.09    8.99

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM