【问题标题】:Managing duplicated rows in large data frames管理大型数据框中的重复行
【发布时间】:2014-06-17 10:53:29
【问题描述】:

我想用E 字符串在同一个no 列中用多个State 标记样本(sample_id 列)。

我的df 数据框输入:

          no               sample_id  State 
chr1-15984544-15996851-0n  NE001788    0n
chr1-15984544-15996851-0n  NE001788    1n
chr1-15984544-15996851-0n  NE001836    0n
chr1-15984544-15996851-0n  NE002026    0n
chr1-15984544-15996851-0n  NE001413    0n
chr1-15984544-15996851-0n  NE001438    0n

我期待的output

          no               sample_id  State 
chr1-15984544-15996851-0n  NE001788    E
chr1-15984544-15996851-0n  NE001836    0n
chr1-15984544-15996851-0n  NE002026    0n
chr1-15984544-15996851-0n  NE001413    0n
chr1-15984544-15996851-0n  NE001438    0n

样本NE001788 被标记为E,因为它在同一个no 字符串中有两种不同的状态(State)。 我曾将以下代码用于小型数据帧:

df <- read.table(text= 'no  sample_id  State 
                 chr1-15984544-15996851-0n  NE001788    0n
                 chr1-15984544-15996851-0n  NE001788    1n
                 chr1-15984544-15996851-0n  NE001836    0n
                 chr1-15984544-15996851-0n  NE002026    0n
                 chr1-15984544-15996851-0n  NE001413    0n
                 chr1-15984544-15996851-0n  NE001438    0n',header=TRUE) 

library(plyr)
output <- unique(ddply(df,.(no,sample_id),mutate,State=if(length(unique(State))>1) {"E"} else State))

它工作正常。但是,我现在有一个大数据框(超过 70 万行)。在这个大数据框中,我得到一个内存错误:cannot allocate vector of size 75kb

我在这里寻求替代方案以达到相同的结果,而不会出现内存突破。

非常感谢。

【问题讨论】:

  • 在您预期的输出中,您删除了重复的行,这是故意的还是错误的?因为您没有在请求中指定
  • 是的,我想删除重复的行并只创建一个带有“E”State 的行。在我的输出中,我不希望两个 no 条目指向同一个 sample_id。当我收到多个条目时,我想创建“E”行。

标签: r memory-management plyr


【解决方案1】:

试试data.table。我没有对这段代码进行基准测试,但它肯定比plyr更好

library(data.table)
df <- setDT(df)[, lapply(.SD, function(x) ifelse(.N > 1, "E", as.character(x))), by = c("no", "sample_id"), .SDcols = "State"]

##                           no sample_id State
## 1: chr1-15984544-15996851-0n  NE001788     E
## 2: chr1-15984544-15996851-0n  NE001836    0n
## 3: chr1-15984544-15996851-0n  NE002026    0n
## 4: chr1-15984544-15996851-0n  NE001413    0n
## 5: chr1-15984544-15996851-0n  NE001438    0n

更好的选择是首先将State 设为一个字符(如果还没有的话)以避免在每个组中执行as.character,然后进行子集化。类似的东西

setDT(df)[, State := as.character(State)]
df <- df[, lapply(.SD, function(x) ifelse(.N > 1, "E", x)), by = c("no", "sample_id"), .SDcols = "State"]

【讨论】:

    【解决方案2】:

    这是执行此操作的 dyplr 代码:

    dd %>%
      mutate(State = as.character(State)) %>%
      group_by(no, sample_id) %>%
      summarize(State = ifelse(length(unique(State)) > 1, "E", State))
    

    很可能,使用dplyr 会比plyr 快​​,但我不知道它在内存使用方面的比较,因为这似乎是您的情况的瓶颈。

    请注意,我在操作之前将State 转换为字符,因为如果您从问题中读取数据,它将是factors。如果实际上他们是角色,当然可以跳过。

    注意:我使用length(unique(State)) &gt; 1 来涵盖nosample_idState 中的条目在多行中都相同的(假设)情况。根据您的描述,您不想在这种情况下将E 分配给State,但尚不清楚您的数据中是否可能出现这种情况。如果没有,您可以将length(unique(State)) &gt; 1 替换为n() &gt; 1

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-04
      • 2020-06-19
      • 2012-07-09
      • 2013-03-04
      • 2020-03-31
      相关资源
      最近更新 更多