将数据框列表转换为列表名称为

时间:2020-02-16 13:00:15

标签: r list dataframe sapply

我希望确定一种将数据帧列表转换为单个数据帧的有效方法。以下是我的可复制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代码,但到目前为止仍未成功。什么是实现此目的的有效方法?

4 个答案:

答案 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)

一个purrrdplyr选项可以是:

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'))
相关问题