編集: OPのコメントの後の新しい解決策。使用するのは非常に簡単data.table
です:
df <- structure(list(Probe.Id = c("1418126_at", "145119_a_at", "1423477_at",
"1434193_at", "100_at"), Gene.Id = c("6352", "2192", NA,
"100506144///9204", "100506144///100506146///100506148///100506150"),
Score.d = c(28.52578, 24.87866, 24.43532, 6.22395, 6.22395)),
.Names = c("Probe.Id", "Gene.Id", "Score.d"), row.names = c(NA, 5L),
class = "data.frame")
require(data.table)
dt <- data.table(df)
dt.out <- dt[, list(Probe.Id = Probe.Id,
Gene.Id = unlist(strsplit(Gene.Id, "///")),
Score.d = Score.d), by=1:nrow(dt)]
> dt.out
# nrow Probe.Id Gene.Id Score.d
# 1: 1 1418126_at 6352 28.52578
# 2: 2 145119_a_at 2192 24.87866
# 3: 3 1423477_at NA 24.43532
# 4: 4 1434193_at 100506144 6.22395
# 5: 4 1434193_at 9204 6.22395
# 6: 5 100_at 100506144 6.22395
# 7: 5 100_at 100506146 6.22395
# 8: 5 100_at 100506148 6.22395
# 9: 5 100_at 100506150 6.22395
が固定パターンの場合は、式に追加fixed = TRUE
してさらに高速化できます。strsplit
///
代替方法再び使用しdata.table
ます。strsplit
これがベクトル化された操作であり、列全体でGene.Id
実行する方が、一度に1行ずつ実行するよりもはるかに高速であることを考慮すると( data.table
thro'は非常に高速に実行されますが、前のコードを分割することで、より高速化できます) 2つのステップに:
# first split using strsplit (data.table can hold list in its columns!!)
dt[, Gene.Id_split := strsplit(dt$Gene.Id, "///", fixed=TRUE)]
# then just unlist them
dt.2 <- dt[, list(Probe.Id = Probe.Id,
Gene.Id = unlist(Gene.Id_split),
Score.d = Score.d), by = 1:nrow(dt)]
data.table
行を取得するまで、この例に示されているものを何度も複製しました295245
。そして、私は以下を使用してベンチマークを実行しましたrbenchmark
:
# first function
DT1 <- function() {
dt.1 <- dt[, list(Probe.Id = Probe.Id,
Gene.Id = unlist(strsplit(Gene.Id, "///", fixed = TRUE)),
Score.d = Score.d), by=1:nrow(dt)]
}
# expected to be faster function
DT2 <- function() {
dt[, Gene.Id_split := strsplit(dt$Gene.Id, "///", fixed=TRUE)]
# then just unlist them
dt.2 <- dt[, list(Probe.Id = Probe.Id, Gene.Id = unlist(Gene.Id_split), Score.d = Score.d), by = 1:nrow(dt)]
}
require(rbenchmark)
benchmark(DT1(), DT2(), replications=10, order="elapsed")
# test replications elapsed relative user.self sys.self
# 2 DT2() 10 15.708 1.000 14.390 0.391
# 1 DT1() 10 24.957 1.589 23.723 0.436
この例では、約1.6倍速くなります。ただし、これは。を含むエントリの数によって異なります///
。お役に立てれば。
古いソリューション:(継続性のために)
1つの方法は、次のとおりです。1)find the positions
これ///
が発生する場所、2)extract
、3)duplicate
、4)sub
、および5)combine
それら。
df <- structure(list(Probe.Id = structure(c(1L, 4L, 2L, 3L),
.Label = c("1418126_at", "1423477_at", "1434193_at", "145119_a_at"),
class = "factor"), Gene.Id = structure(c(3L, 2L, NA, 1L),
.Label = c("100506144///9204", "2192", "6352"), class = "factor"),
Score.d = c(28.52578, 24.87866, 24.43532, 6.22395)),
.Names = c("Probe.Id", "Gene.Id", "Score.d"),
class = "data.frame", row.names = c(NA, -4L))
# 1) get the positions of "///"
idx <- grepl("[/]{3}", df$Gene.Id)
# 2) create 3 data.frames
df1 <- df[!idx, ] # don't touch this.
df2 <- df[idx, ] # we need to work on this
# 3) duplicate
df3 <- df2 # duplicate it.
4) sub
df2$Gene.Id <- sub("[/]{3}.*$", "", df2$Gene.Id) # replace the end
df3$Gene.Id <- sub("^.*[/]{3}", "", df3$Gene.Id) # replace the beginning
# 5) combine/put them back
df.out <- rbind(df1, df2, df3)
# if necessary sort them here.