我希望确定一种将数据帧列表转换为单个数据帧的有效方法。以下是我的可复制MWE:
set.seed(1)
ABAge = runif(100)
ABPoints = rnorm(100)
ACAge = runif(100)
ACPoints = rnorm(100)
BCAge = runif(100)
BCPoints = rnorm(100)
A_B <- data.frame(ID = as.character(paste0("ID", 1:100)), Age = ABAge, Points = ABPoints)
A_C <- data.frame(ID = as.character(paste0("ID", 1:100)), Age = ACAge, Points = ACPoints)
B_C <- data.frame(ID = as.character(paste0("ID", 1:100)), Age = BCAge, Points = BCPoints)
A_B$ID <- as.character(A_B$ID)
A_C$ID <- as.character(A_C$ID)
B_C$ID <- as.character(B_C$ID)
listFormat <- list("A_B" = A_B, "A_C" = A_C, "B_C" = B_C)
dfFormat <- data.frame(ID = as.character(paste0("ID", 1:100)), A_B.Age = ABAge, A_B.Points = ABPoints, A_C.Age = ACAge, A_C.Points = ACPoints, B_C.Age = BCAge, B_C.Points = BCPoints)
dfFormat$ID = as.character(dfFormat$ID)
这将导致数据帧格式(dfFormat
)如下所示:
'data.frame': 100 obs. of 7 variables:
$ ID : chr "ID1" "ID2" "ID3" "ID4" ...
$ A_B.Age : num 0.266 0.372 0.573 0.908 0.202 ...
$ A_B.Points: num 0.398 -0.612 0.341 -1.129 1.433 ...
$ A_C.Age : num 0.6737 0.0949 0.4926 0.4616 0.3752 ...
$ A_C.Points: num 0.409 1.689 1.587 -0.331 -2.285 ...
$ B_C.Age : num 0.814 0.929 0.147 0.75 0.976 ...
$ B_C.Points: num 1.474 0.677 0.38 -0.193 1.578 ...
以及如下所示的数据帧列表listFormat
:
List of 3
$ A_B:'data.frame': 100 obs. of 3 variables:
..$ ID : chr [1:100] "ID1" "ID2" "ID3" "ID4" ...
..$ Age : num [1:100] 0.266 0.372 0.573 0.908 0.202 ...
..$ Points: num [1:100] 0.398 -0.612 0.341 -1.129 1.433 ...
$ A_C:'data.frame': 100 obs. of 3 variables:
..$ ID : chr [1:100] "ID1" "ID2" "ID3" "ID4" ...
..$ Age : num [1:100] 0.6737 0.0949 0.4926 0.4616 0.3752 ...
..$ Points: num [1:100] 0.409 1.689 1.587 -0.331 -2.285 ...
$ B_C:'data.frame': 100 obs. of 3 variables:
..$ ID : chr [1:100] "ID1" "ID2" "ID3" "ID4" ...
..$ Age : num [1:100] 0.814 0.929 0.147 0.75 0.976 ...
..$ Points: num [1:100] 1.474 0.677 0.38 -0.193 1.578 ...
我希望提出一种自动方法,将dfFormat
转换为listFormat
。从以上对象可以看出,有两个主要条件:
1)如果listFormat
的每个子列表中有一个公共列(名称和内容)(在这些示例中为ID
),则在输出的dfFormat
中不会重复它们(在此示例中,它有最后一个ID
列)
2)listFormat
子列表中的其余列名称将成为dfFormat
中的列,并且具有这样的名称:它们保留其子列表名称(即“ A_B”),后跟一个点,然后是一个原始列名(即Age),使其在dfFormat
中成为(即“ A_B.Age”)。
我尝试了各种unlist()
和sapply
代码,但到目前为止仍未成功。什么是实现此目的的有效方法?
答案 0 :(得分:1)
将listFormat
复制到L
,以防我们需要保留输入listFormat
。从ID
的每个组成部分中除去L
列,除了第一个cbind
我们剩下的东西,然后确定第一列的名称。不使用任何软件包。
L <- listFormat
L[-1] <- lapply(L[-1], transform, ID = NULL)
DF <- do.call(cbind, L)
names(DF)[1] <- "ID"
给予:
> str(DF)
'data.frame': 100 obs. of 7 variables:
$ ID : chr "ID1" "ID2" "ID3" "ID4" ...
$ A_B.Age : num 0.9932 0.1451 0.6166 0.0372 0.9039 ...
$ A_B.Points: num 0.4752 0.0288 1.0548 0.6113 0.0651 ...
$ A_C.Age : num 0.912 0.761 0.618 0.895 0.507 ...
$ A_C.Points: num -0.515 -0.945 0.398 0.502 -1.021 ...
$ B_C.Age : num 0.7935 0.2747 0.0487 0.6307 0.3499 ...
$ B_C.Points: num -0.963 -1.772 1.716 -0.819 0.577 ...
答案 1 :(得分:0)
您正在寻找dplyr::bind_rows
:
library(dplyr)
bind_rows(listFormat, .id = "name")
输出:
name ID Age Points
1 A_B ID1 0.2655087 0.3981059
2 A_B ID2 0.3721239 -0.6120264
3 A_B ID3 0.5728534 0.3411197
4 A_B ID4 0.9082078 -1.1293631
5 A_B ID5 0.2016819 1.4330237
6 A_B ID6 0.8983897 1.9803999
答案 2 :(得分:0)
一个purrr
和dplyr
选项可以是:
imap(listFormat, ~ setNames(.x, paste(rep(.y, length(.x)), names(.x), sep = ".")) %>%
rename_at(vars(ends_with("ID")), ~ "ID")) %>%
reduce(full_join, by = "ID")
ID A_B.Age A_B.Points A_C.Age A_C.Points B_C.Age B_C.Points
1 ID1 0.26550866 0.398105880 0.67371223 0.409401840 0.81425175 1.473881181
2 ID2 0.37212390 -0.612026393 0.09485786 1.688873286 0.92877723 0.677268492
3 ID3 0.57285336 0.341119691 0.49259612 1.586588433 0.14748105 0.379962687
4 ID4 0.90820779 -1.129363096 0.46155184 -0.330907801 0.74982166 -0.192798426
5 ID5 0.20168193 1.433023702 0.37521653 -2.285235535 0.97565735 1.577891795
6 ID6 0.89838968 1.980399899 0.99109922 2.497661590 0.97479246 0.596234109
7 ID7 0.94467527 -0.367221476 0.17635071 0.667066167 0.35062557 -1.173576941
8 ID8 0.66079779 -1.044134626 0.81343521 0.541327336 0.39394906 -0.155642535
9 ID9 0.62911404 0.569719627 0.06844664 -0.013399523 0.95095101 -1.918909820
10 ID10 0.06178627 -0.135054604 0.40044975 0.510108423 0.10664832 -0.195258846
答案 3 :(得分:0)
鉴于每个data.frame具有相同的ID列,因此在R中非常简单。
as.data.frame(listFormat)
# A_B.ID A_B.Age A_B.Points A_C.ID A_C.Age A_C.Points B_C.ID B_C.Age B_C.Points
# 1 ID1 0.2655087 0.3981059 ID1 0.67371223 0.4094018 ID1 0.8142518 1.4738812
# 2 ID2 0.3721239 -0.6120264 ID2 0.09485786 1.6888733 ID2 0.9287772 0.6772685
# 3 ID3 0.5728534 0.3411197 ID3 0.49259612 1.5865884 ID3 0.1474810 0.3799627
# 4 ID4 0.9082078 -1.1293631 ID4 0.46155184 -0.3309078 ID4 0.7498217 -0.1927984
# 5 ID5 0.2016819 1.4330237 ID5 0.37521653 -2.2852355 ID5 0.9756573 1.5778918
# 6 ID6 0.8983897 1.9803999 ID6 0.99109922 2.4976616 ID6 0.9747925 0.5962341
您为每个data.frame都有一个ID列,但这可以很容易地整理
如果在每个data.frame的id列不同的情况下需要更通用的解决方案,则可以使用library(data.table)
DTFormat = rbindlist(listFormat, idcol = T)
dcast(DTFormat, ID~.id, value.var = c('Age', 'Points'))