【问题标题】:transposing a dataframe with repeats转置重复的数据帧
【发布时间】:2017-08-14 19:49:07
【问题描述】:

我有一个数据框,它有两列,一列用于基因符号,另一列用于功能通路。路径列具有重复值,因为每个路径都有许多基因。我想对这个数据集重新排序,以便每一列都是一条通路,而这些列中的每一行都是属于该通路的一个基因。

起始数据框:

data.frame(pathway = c("p1", "p1", "p1", "p1", "p2", "p2", "p2"), 
gene.symbol = c("G1", "G2", "G3", "G4", "G33", "G43", "G10"))

所需的数据框:

data.frame(p1 = c("G1", "G2", "G3", "G4"), p2 = c("G33", "G43", "G10", 
""))

我知道并非所有列的长度都相同,并且使用空白值比 NA 更可取。

【问题讨论】:

  • 由于列的长度不同,你最好创建一个标准的list而不是data.frame,特别是因为第1行,第1列与第 1 行,第 2 列。

标签: r


【解决方案1】:

这是另一种选择。

  1. 使用路径作为拆分元素拆分为列表
  2. 获取每个组的最大长度,并将所有其他组设置为相同长度
  3. 将其转回数据框

这里是代码。

mydf <- data.frame(pathway = c("p1", "p1", "p1", "p1", "p2", "p2", "p2"), 
           gene.symbol = c("G1", "G2", "G3", "G4", "G33", "G43", "G10"))

# function to run over each element in list
set_to_max_length <- function(x) {
  length(x) <- max.length
  return(x)
}

# 1. split into  list
mydf.split <- split(mydf$gene.symbol, mydf$pathway)

# 2.a get max length of all columns
max.length <- max(sapply(mydf.split, length))

# 2.b set each list element to max length
mydf.split.2 <- lapply(mydf.split, set_to_max_length)

# 3. combine back into df
data.frame(mydf.split.2)

编辑

这是使用 tidyverse 的另一个选项 - 更简洁一些:

library(tidyverse)
mydf <- data.frame(pathway = c("p1", "p1", "p1", "p1", "p2", "p2", "p2"), 
                   gene.symbol = c("G1", "G2", "G3", "G4", "G33", "G43", "G10"))

mydf %>% 
  group_by(pathway) %>% 
  mutate(rownum = row_number()) %>% 
  ungroup() %>% 
  spread(pathway, gene.symbol) %>% 
  select(-1)

【讨论】:

    【解决方案2】:

    这可能看起来有点令人费解,但它通过首先进入列表而不是返回 data.frame 来实现所需的输出:

    df$gene.symbol <- as.character(df$gene.symbol)
    
    pw_list <- list()
    for (pw in unique(df$pathway)) {
      pw_list[[pw]] <- df[df$pathway == pw, "gene.symbol"]
    }
    pw_list
    $p1
    [1] "G1" "G2" "G3" "G4"
    
    $p2
    [1] "G33" "G43" "G10"
    
    
    reordered <- matrix("", nrow = max(sapply(pw_list, length)), ncol = length(pw_list))
    colnames(reordered) <- names(pw_list)
    
    for (pw in names(pw_list)){
      n <- length(pw_list[[pw]])
      reordered[1:n, pw] <- pw_list[[pw]]
    }
    reordered <- as.data.frame(reordered)
    reordered
      p1  p2
    1 G1 G33
    2 G2 G43
    3 G3 G10
    4 G4    
    

    编辑

    稍微简洁一点的版本:

    df$gene.symbol <- as.character(df$gene.symbol)
    pw_list <- list()
    for (pw in unique(df$pathway)) {
      pw_list[[pw]] <- df[df$pathway == pw, "gene.symbol"]
    }
    reordered <- as.data.frame(sapply(pw_list, "[", i = 1:max(sapply(pw_list, length))), 
                               stringsAsFactors = FALSE)
    reordered[is.na(reordered)] <- ""
    names(reordered) <- names(pw_list)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-16
      • 2019-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-21
      相关资源
      最近更新 更多