将矩阵值转换为具有给定值的单元格数

Convert matrix values to number of cells with a given value

我有一个包含 5 列的 data.frame,每列占整体的一部分。这是它的样子:

Sample    Type_A    Type_B    Type_C    Type_D    Type_E    Sum
00001      54        13         24        3          6      100
00002      5         2          15        54        24      100
00003      10        10         23        37        20      100

我想创建一个包含 100 列的 matrix 并根据我的 data.frame 中的值按比例填充单元格。第 00001 行看起来在前 50 个单元格中有 A,然后是 13 个单元格中有 B,然后是 24 个单元格中有 C,等等

所需的矩阵如下所示:

00001  A  A  A  A  A  A  A  A  A  A  A  A  A  A .....
00002  A  A  A  A  A  B  B  C  C  C  C  C  C  C .....
00003  A  A  A  A  A  A  A  A  A  A  B  B  B  B .....

请注意,您的第一个样本加起来不是 100,而是 96。为了便于示例,我将使用 54。

尝试rep

rep(c("A","B","C","D","E"),c(54,13,24,3,6))

# "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A"
# "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "A" "B" "B" "B" "B" "B" "B" "B" "B"
# "B" "B" "B" "B" "B" "C" "C" "C" "C" "C" "C" "C" "C" "C" "C" "C" "C" "C" "C" "C" "C" "C" "C" "C" "C" "C" "C" "C" "C" "D" "D"
# "D" "E" "E" "E" "E" "E" "E"

对于你的数据框,我会做这样的事情(但它可能可以用更少的代码完成):

# Some preparation
df2 <- df[,2:(ncol(df)-1)] # selecting just the types
names(df2) <- gsub("Type_", "", names(df2)) # Removing "Type_" from the variable names

# Apply rep to all rows
lis <- apply(df2,1,function(x) rep(names(df2),x))
t(as.matrix(lis))

如果可以的话,我有一个快速的 hacky 解决方案。首先我制作了一些假数据 semi-matches 你的数据 semi-provided.

library(plyr)
dat <-  matrix(c(50,14,24,12, 50,50,0,0), ncol=4, byrow=TRUE)
colnames(dat) <- paste('Type_', LETTERS[1:4], sep='')

然后我使用一个非常笨拙的 strsplit 命令从 colnames 中取出字母,并使用 apply 语句根据值 rep 字母在细胞中。请注意,如果您的行总和不等于 100,它将不起作用。

adply(data,1,function(x){
     nms <- unlist(lapply(strsplit(colnames(dat), '_'), function(x)x[2]))
     rep(nms, x)})[,-1]

这是 data.table 的另一个选项(假设所有行的 "Type" 列中的值总和为 100)。

library(data.table)
nm1 <- sub(".*_", "", grep("_", names(df1), value=TRUE))
setDT(df1)[, transpose(list(rep(nm1, unlist(.SD)))),
    by = Sample ,.SDcols = Type_A:Type_E]
# Sample V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14 V15 V16 V17 V18 V19 V20 V21 V22 V23 V24 V25 V26 V27 V28 V29 V30 V31 V32 V33 V34 V35 V36 V37 V38 V39 V40 V41 V42 V43 V44 V45 V46 V47 V48
#1:  00001  A  A  A  A  A  A  A  A  A   A   A   A   A   A   A   A   A   A   A   A   A   A   A   A   A   A   A   A   A   A   A   A   A   A   A   A   A   A   A   A   A   A   A   A   A   A   A   A
#2:  00002  A  A  A  A  A  B  B  C  C   C   C   C   C   C   C   C   C   C   C   C   C   C   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D
#3:  00003  A  A  A  A  A  A  A  A  A   A   B   B   B   B   B   B   B   B   B   B   C   C   C   C   C   C   C   C   C   C   C   C   C   C   C   C   C   C   C   C   C   C   C   D   D   D   D   D
#   V49 V50 V51 V52 V53 V54 V55 V56 V57 V58 V59 V60 V61 V62 V63 V64 V65 V66 V67 V68 V69 V70 V71 V72 V73 V74 V75 V76 V77 V78 V79 V80 V81 V82 V83 V84 V85 V86 V87 V88 V89 V90 V91 V92 V93 V94 V95
#1:   A   A   A   A   A   A   B   B   B   B   B   B   B   B   B   B   B   B   B   C   C   C   C   C   C   C   C   C   C   C   C   C   C   C   C   C   C   C   C   C   C   C   C   D   D   D   E
#2:   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   E   E   E   E   E   E   E   E   E   E   E   E   E   E   E   E   E   E   E
#3:   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   D   E   E   E   E   E   E   E   E   E   E   E   E   E   E   E
#   V96 V97 V98 V99 V100
#1:   E   E   E   E    E
#2:   E   E   E   E    E
#3:   E   E   E   E    E

这里是 dplyrtidyr 的解决方案。可能有更简洁的方法来处理这个

### Vectorize "rep"
vec_rep <- function(x,y) {
    unlist(lapply(1:length(x), function(z) { paste(rep(x[z], y[z]), collapse = '') }))
}

df2 <-
    df %>%
    select(-Sum)                                    %>% # Col not needed
    gather(Type, TypeVal, -Sample)                  %>% # Reshape data to long format
    mutate(tstr = vec_rep(gsub('^[^_]+_','', Type), TypeVal)) %>% # create strings of desired lengths
    arrange(Sample, Type)                           %>% # Sort
    group_by(Sample)                                %>% # 
    summarise(NewVal = paste(tstr, collapse=''))        # Create desired string based on grouping

df2是一个可以转化为矩阵的数据框