管理大型数据框中的重复行

时间:2014-06-17 10:53:29

标签: r memory-management plyr

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

我的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,因为它在同一个State字符串中有两种不同的状态(no)。 我使用下面的代码来处理小数据帧:

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

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

我在这里要求替代方案达到相同的结果,没有内存突破。

非常感谢。

2 个答案:

答案 0 :(得分:3)

试试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"]

答案 1 :(得分:1)

这里有dyplr代码:

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

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

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

注意:我使用length(unique(State)) > 1来涵盖(假设)nosample_idState中的条目在多行中都相同的情况。根据您的说明,在这种情况下,您不希望将E分配给State,但不清楚您的数据中是否可以存在此类情况。如果没有,您可以将length(unique(State)) > 1替换为n() > 1