2012-01-04 72 views
4

我已經搜索了互聯網,但我一直沒有找到解決我的問題。 我有數字和字符的數據幀:R重複元素的數據幀

mydf <- data.frame(col1=c(1, 2, 3, 4), 
        col2 = c(5, 6, 7, 8), 
        col3 = c("a", "b", "c", "d"), stringsAsFactors = FALSE) 

是myDF:

col1 col2 col3 
    1 5 a 
    2 6 b 
    3 7 c 
    4 8 d 

我想重複到

col1 col2 col3 
    1 5 a 
    1 5 a 
    1 5 a 
    2 6 b 
    2 6 b 
    2 6 b 
    3 7 c 
    3 7 c 
    3 7 c 
    4 8 d 
    4 8 d 
    4 8 d 

此使用apply(mydf, 2, function(x) rep(x, each = 3))會給出正確的重複,但我不會將col1,col2和col3的類別分別保存爲數字,數字和字符。這是一個構建的例子,並且在我的數據框中設置每列的類是有點乏味的。

有沒有辦法讓重複,同時保存類?

回答

4

這是一個不幸的和意想不到的班級轉換(反正我也是)。這是一個簡單的解決方法,它使用data.frame只是一個特殊的列表。

data.frame(lapply(mydf, function(x) rep(x, each = 3))) 

(誰知道爲什麼提問者觀察到的行爲不應該被報告爲錯誤?)

+0

這樣做的竅門!非常感謝! – Sisse 2012-01-04 13:16:24

1

raster包看看aggregatedisaggregate。或者,使用下面我修改的版本zexpand

# zexpand: analogous to disaggregate 

zexpand<-function(inarray, fact=2, interp=FALSE, ...) { 
# do same analysis of fact to allow one or two values, fact >=1 required, etc. 
fact<-as.integer(round(fact)) 
switch(as.character(length(fact)), 
      '1' = xfact<-yfact<-fact, 
      '2'= {xfact<-fact[1]; yfact<-fact[2]}, 
      {xfact<-fact[1]; yfact<-fact[2];warning(' fact is too long. First two values used.')}) 
if (xfact < 1) { stop('fact[1] must be > 0') } 
if (yfact < 1) { stop('fact[2] must be > 0') } 

bigtmp <- matrix(rep(t(inarray), each=xfact), nrow(inarray), ncol(inarray)*xfact, byr=T) #does column expansion 
bigx <- t(matrix(rep((bigtmp),each=yfact),ncol(bigtmp),nrow(bigtmp)*yfact,byr=T)) 
# the interpolation would go here. Or use interp.loess on output (won't 
# handle complex data). Also, look at fields::Tps which probably does 
# a much better job anyway. Just do separately on Re and Im data 
return(invisible(bigx)) 
} 
10

它比你想象的更容易。

index <- rep(seq_len(nrow(mydf)), each = 3) 
mydf[index, ] 

這也避免了來自apply的隱式循環。

+0

聽起來像是時候重寫'zexpand' :-) – 2012-01-04 13:50:03

+0

謝謝大家的幫助和評論! – Sisse 2012-01-04 14:13:58

1

我真的很喜歡Richie Cotton的回答。

但您也可以簡單地使用rbind並對其重新排序。

res <-rbind(mydf,mydf,mydf) 
res[order(res[,1],res[,2],res[,3]),] 
2

只是另一種解決方案:

mydf3 <- do.call(rbind, rep(list(mydf), 3)) 
0

mefa有一個很好的包裝爲rep應用於data.frame。這將匹配您的示例在一條線上:

mefa:::rep.data.frame(mydf, each=3)