R - Creating/subset 循环或应用系列中的数据帧

R - Creating/subset dataframes within loop or apply family

如果多个变量(以相同后缀结尾)不包含 NA,我想对 R 数据帧进行子集化。

employee <- c('John Doe','Peter Gynn','Jolie Hope')
salary1 <- c(NA, 20400, 26800)
salary2 <- c(29045, NA, 78765)
date1 <- as.Date(c(NA,'2008-3-25','2007-3-14'))
date2 <- as.Date(c('2010-11-1',NA,'2007-3-14'))

employ.data <- data.frame(employee, salary1, salary2, date1, date2)

for (i in 1:2) {
  assign("employ.data", i, subset(employ.data, !is.na(employ.data$date[i]) & !is.na(employ.data$salary[i])))
}

最终结果有望产生两个独立的数据帧,如下所示:

employ.data1:
| employee   | salary1 | salary2 | date1      | date2      |
| Peter Gynn | 20400   | NA      | 2008-03-25 | NA         |
| Jolie Hope | 26800   | 78765   | 2007-03-14 | 2007-03-14 |

employ.data2:
| employee   | salary1 | salary2 | date1      | date2      |
| John Doe   | NA      | 29045   | NA         | 2010-11-01 |
| Jolie Hope | 26800   | 78765   | 2007-03-14 | 2007-03-14 |

提前致谢!

(预先:处理 list of frames 通常比使用 assign 动态创建对象更好。)

numfields <- grep("[0-9]+$", colnames(employ.data), value = TRUE)
split(numfields, gsub(".*?([0-9]+)$", "\1", numfields))
# $`1`
# [1] "salary1" "date1"  
# $`2`
# [1] "salary2" "date2"  
out <- lapply(split(numfields, gsub(".*?([0-9]+)$", "\1", numfields)),
              function(flds) employ.data[ complete.cases(subset(employ.data, select = flds)), ])
out
# $`1`
#     employee salary1 salary2      date1      date2
# 2 Peter Gynn   20400      NA 2008-03-25       <NA>
# 3 Jolie Hope   26800   78765 2007-03-14 2007-03-14
# $`2`
#     employee salary1 salary2      date1      date2
# 1   John Doe      NA   29045       <NA> 2010-11-01
# 3 Jolie Hope   26800   78765 2007-03-14 2007-03-14

这将动态查找所有带编号的字段,但不可否认它不强制“成对”。

non_na函数returns在名称以 i 结尾的列中没有缺失值的行。它首先将这些列名称定义为 cn,然后使用 complete.cases 定义一个逻辑向量,指示哪些行在这些列中没有 NA,然后 returns 来自 employ.data.[=16 的那些行=]

假设列中唯一的数字位于名称的末尾,并且唯一的此类数字定义了可能的后缀。词干是去除后缀后的那些唯一名称。
我们假设第 1 列将被排除在该计算之外。我们使用 gsub/unique 来定义后缀和词干。或者硬编码 suffixes <- as.character(1:2)stems <- c("salary", "date") .

最后 运行 non_na 在每个后缀上创建一个列表,其 i 组件包含一个数据框,其中的行对应于 i。 L[[i]] 将是第 i 个数据框。

non_na <- function(i) {
  cn <- paste0(stems, i)
  employ.data[complete.cases(employ.data[cn]), ]
}

nms <- names(employ.data)[-1]
suffixes <- unique(gsub("\D", "", nms)) # c("1", "2")
stems <- unique(gsub("\d", "", nms)) # c("salary", "date")
L <- Map(non_na, suffixes); L

给予:

$`1`
    employee salary1 salary2      date1      date2
2 Peter Gynn   20400      NA 2008-03-25       <NA>
3 Jolie Hope   26800   78765 2007-03-14 2007-03-14

$`2`
    employee salary1 salary2      date1      date2
1   John Doe      NA   29045       <NA> 2010-11-01
3 Jolie Hope   26800   78765 2007-03-14 2007-03-14