根据多列和每个嵌套数据框的 select 特定列将数据框拆分为多个数据框的列表

Split dataframe into list of multiple dataframes based on multiple columns and select specific columns for each nested dataframe

我有一个这样的数据框:

|DOI                           | WoS| Scopus| Dim| WoS_Year| Scopus_Year| Dim_Year|
|:-----------------------------|---:|------:|---:|--------:|-----------:|--------:|
|10.1515/jag-2017-0010         |  NA|      1|   1|       NA|        2017|     2017|
|10.1007/978-3-662-55771-6_9   |  NA|     NA|   1|       NA|          NA|     2020|
|10.1088/1361-6668/30/2/024004 |   1|      1|  NA|     2017|        2017|       NA|
|10.3390/ma12010124            |   1|      1|  NA|     2019|        2019|       NA|
|10.1002/ppsc.201700109        |   1|      1|   1|     2017|        2017|     2017|

我想把它分成一个包含 3 个数据帧的列表 (list_of_df),其中:

(实际上有多个以 WoS_*Scopus_*Dim_* 开头的列,我希望每个列都保留在新的相应 list_of_df 中,但是删除起始字符串,如 WoS_

例如,所有 starting_with("Scopus_") 的列都应该在 list_of_df$Scopus 中,但列名称中没有 Scopus_。)

实现此目标的最佳方法是什么?

我对 list_of_df <- split(df, with(df, interaction(WoS,Scopus,Dim)), drop = TRUE)dplyr::nest(df, WoS:Dim) 的尝试没有结果...

感谢您的帮助!

> dput(df)

structure(list(DOI = c("10.1515/jag-2017-0010", "10.1007/978-3-662-55771-6_9", 
"10.1088/1361-6668/30/2/024004", "10.3390/ma12010124", "10.1002/ppsc.201700109"
), WoS = c(NA, NA, 1L, 1L, 1L), Scopus = c(1L, NA, 1L, 1L, 1L
), Dim = c(1L, 1L, NA, NA, 1L), WoS_Year = c(NA, NA, 2017L, 2019L, 
2017L), Scopus_Year = c(2017L, NA, 2017L, 2019L, 2017L), Dim_Year = c(2017L, 
2020L, NA, NA, 2017L)), row.names = c(2186L, 9505L, 12281L, 11882L, 
874L), class = "data.frame")

在基础 R 中你可以这样做:

df1 <- subset(reshape(df, matrix(2:ncol(df),2, byrow=TRUE), dir="long", idvar = "DOI", 
                       times = c("WoS","Scopus","Dim")), WoS==1)
rownames(df1)<-NULL
split(df1, df1$time)

$Dim
                           DOI time WoS WoS_Year
8        10.1515/jag-2017-0010  Dim   1     2017
9  10.1007/978-3-662-55771-6_9  Dim   1     2020
10      10.1002/ppsc.201700109  Dim   1     2017

$Scopus
                            DOI   time WoS WoS_Year
4         10.1515/jag-2017-0010 Scopus   1     2017
5 10.1088/1361-6668/30/2/024004 Scopus   1     2017
6            10.3390/ma12010124 Scopus   1     2019
7        10.1002/ppsc.201700109 Scopus   1     2017

$WoS
                            DOI time WoS WoS_Year
1 10.1088/1361-6668/30/2/024004  WoS   1     2017
2            10.3390/ma12010124  WoS   1     2019
3        10.1002/ppsc.201700109  WoS   1     2017

您可以更改列名以符合您的需要

另一种方式:

lapply(split.default(df[-1],sub("_.*","",names(df[-1]))),
        function(x)na.omit(cbind(df[1], x)[x[[1]]==1,]))
$Dim
                             DOI Dim Dim_Year
2186       10.1515/jag-2017-0010   1     2017
9505 10.1007/978-3-662-55771-6_9   1     2020
874       10.1002/ppsc.201700109   1     2017

$Scopus
                                DOI Scopus Scopus_Year
2186          10.1515/jag-2017-0010      1        2017
12281 10.1088/1361-6668/30/2/024004      1        2017
11882            10.3390/ma12010124      1        2019
874          10.1002/ppsc.201700109      1        2017

$WoS
                                DOI WoS WoS_Year
12281 10.1088/1361-6668/30/2/024004   1     2017
11882            10.3390/ma12010124   1     2019
874          10.1002/ppsc.201700109   1     2017

另外一个在 base R 中,如果这是预期的输出

res=list()
for (k in c("WoS","Scopus","Dim")) {
  res[[k]]=df[df[,k]==1 & !is.na(df[,k]),grepl(k,colnames(df)) | c(TRUE,rep(FALSE,ncol(df)-1))]
  colnames(res[[k]])=gsub(paste0(k,"_"),"",colnames(res[[k]]))
}

$WoS
                                DOI WoS Year
12281 10.1088/1361-6668/30/2/024004   1 2017
11882            10.3390/ma12010124   1 2019
874          10.1002/ppsc.201700109   1 2017

$Scopus
                                DOI Scopus Year
2186          10.1515/jag-2017-0010      1 2017
12281 10.1088/1361-6668/30/2/024004      1 2017
11882            10.3390/ma12010124      1 2019
874          10.1002/ppsc.201700109      1 2017

$Dim
                             DOI Dim Year
2186       10.1515/jag-2017-0010   1 2017
9505 10.1007/978-3-662-55771-6_9   1 2020
874       10.1002/ppsc.201700109   1 2017