多次向数据框添加一组行

时间:2013-12-30 16:16:04

标签: r dataframe

我有一个带有分组行和列的数据框,并希望根据另一个数据框中包含的信息多次添加整个行组。在示例数据中,我通过三次复制id为1(1990年1月1日)的行显示了我希望得到的最终输出。变量“dups”表示该组应被复制的次数。

以下是dput示例:

> dput(df)
structure(list(date = c("01-jan-90", "01-jan-90", "01-jan-90", 
"01-jan-90", "01-jan-90", "02-jan-90", "02-jan-90", "02-jan-90", 
"02-jan-90", "02-jan-90"), rdate = c("08-jan-90", "15-jan-90", 
"01-jan-90", "22-jan-90", "29-jan-90", "09-jan-90", "16-jan-90", 
"02-jan-90", "23-jan-90", "30-jan-90"), id = c(1L, 1L, 1L, 1L, 
1L, 2L, 2L, 2L, 2L, 2L)), datalabel = "", time.stamp = "30 Dec 2013 16:39", .Names = c("date", 
"rdate", "id"), formats = c("%9s", "%9s", "%8.0g"), types = c(9L, 
9L, 251L), val.labels = c("", "", ""), var.labels = c("", "", 
""), row.names = c("1", "2", "3", "4", "5", "6", "7", "8", "9", 
"10"), version = 12L, class = "data.frame")

以下是有关日期和复制次数的信息:

date    dups    id
01-jan-90   3   1
02-jan-90   2   2

1990年1月1日ID 1的输出如下:

      date     rdate id newid
1  01-jan-90 08-jan-90  1     1
2  01-jan-90 15-jan-90  1     1
3  01-jan-90 01-jan-90  1     1
4  01-jan-90 22-jan-90  1     1
5  01-jan-90 29-jan-90  1     1
6  01-jan-90 08-jan-90  1     2
7  01-jan-90 15-jan-90  1     2
8  01-jan-90 01-jan-90  1     2
9  01-jan-90 22-jan-90  1     2
10 01-jan-90 29-jan-90  1     2
11 01-jan-90 08-jan-90  1     3
12 01-jan-90 15-jan-90  1     3
13 01-jan-90 01-jan-90  1     3
14 01-jan-90 22-jan-90  1     3
15 01-jan-90 29-jan-90  1     3

3 个答案:

答案 0 :(得分:1)

df2 <- read.table(textConnection("date dups id
01-jan-90 3 1
02-jan-90 2 2"), sep=" ", header=T)

dup <- function(df, date, num) {
  i <- which(df$date==date)
  cbind(df[rep(i,num),], newid=rep(1:num, each=length(i)))
}

df3 <- data.frame()
for (x in 1:nrow(df2)) {
  df3 <- rbind(df3, dup(df, df2$date[x], df2$dups[x]))
}
df3
#           date     rdate id newid
# 1    01-jan-90 08-jan-90  1     1
# 2    01-jan-90 15-jan-90  1     1
# 3    01-jan-90 01-jan-90  1     1
# 4    01-jan-90 22-jan-90  1     1
# 5    01-jan-90 29-jan-90  1     1
# 1.1  01-jan-90 08-jan-90  1     2
# 2.1  01-jan-90 15-jan-90  1     2
# 3.1  01-jan-90 01-jan-90  1     2
# 4.1  01-jan-90 22-jan-90  1     2
# 5.1  01-jan-90 29-jan-90  1     2
# 1.2  01-jan-90 08-jan-90  1     3
# 2.2  01-jan-90 15-jan-90  1     3
# 3.2  01-jan-90 01-jan-90  1     3
# 4.2  01-jan-90 22-jan-90  1     3
# 5.2  01-jan-90 29-jan-90  1     3
# 6    02-jan-90 09-jan-90  2     1
# 7    02-jan-90 16-jan-90  2     1
# 8    02-jan-90 02-jan-90  2     1
# 9    02-jan-90 23-jan-90  2     1
# 10   02-jan-90 30-jan-90  2     1
# 6.1  02-jan-90 09-jan-90  2     2
# 7.1  02-jan-90 16-jan-90  2     2
# 8.1  02-jan-90 02-jan-90  2     2
# 9.1  02-jan-90 23-jan-90  2     2
# 10.1 02-jan-90 30-jan-90  2     2

答案 1 :(得分:1)

使用merge

这是一种相当简单的方法

首先,我们假设您的“复制器”data.frame被称为“mydf”。其次,merge,创建sequence列的dups,“展开”您的行,并重新绑定新ID。

A <- merge(df, mydf)
newID <- sequence(A$dups)
out <- cbind(A[rep(rownames(A), A$dups), c("date", "id", "rdate")], newID)
head(out)
#          date id     rdate newID
# 1   01-jan-90  1 08-jan-90     1
# 1.1 01-jan-90  1 08-jan-90     2
# 1.2 01-jan-90  1 08-jan-90     3
# 2   01-jan-90  1 15-jan-90     1
# 2.1 01-jan-90  1 15-jan-90     2
# 2.2 01-jan-90  1 15-jan-90     3

订单与您的示例输出不同,但使用order很容易解决,如下所示:

outordered <- out[with(out, do.call(order, list(date, id, newID))), ]
head(outordered, 10)
#          date id     rdate newID
# 1   01-jan-90  1 08-jan-90     1
# 2   01-jan-90  1 15-jan-90     1
# 3   01-jan-90  1 01-jan-90     1
# 4   01-jan-90  1 22-jan-90     1
# 5   01-jan-90  1 29-jan-90     1
# 1.1 01-jan-90  1 08-jan-90     2
# 2.1 01-jan-90  1 15-jan-90     2
# 3.1 01-jan-90  1 01-jan-90     2
# 4.1 01-jan-90  1 22-jan-90     2
# 5.1 01-jan-90  1 29-jan-90     2
tail(outordered)
#           date id     rdate newID
# 10   02-jan-90  2 30-jan-90     1
# 6.1  02-jan-90  2 09-jan-90     2
# 7.1  02-jan-90  2 16-jan-90     2
# 8.1  02-jan-90  2 02-jan-90     2
# 9.1  02-jan-90  2 23-jan-90     2
# 10.1 02-jan-90  2 30-jan-90     2

答案 2 :(得分:1)

# Create the data.frame with the number of duplications
# assuming it is unique on date/id

id <- unique(df[, c("date", "id")])
id$dups <- c(3, 2)
library(plyr)

# Use ddply to cycle through the id df, and lapply to
# duplicate the df

ddply(id, c("date", "id"), 
  function(df.sub) {
    if(nrow(df.sub) != 1L) stop("Logic error") # id df shoudl be unique on date/id
    df.to.rep <- subset(df, date==df.sub$date & id==df.sub$id)
    df.rep <- lapply(1:df.sub$dups, function(newid) transform(df.to.rep, newid=newid))
    do.call(rbind, df.rep)
  }
)

#         date     rdate id newid
# 1  01-jan-90 08-jan-90  1     1
# 2  01-jan-90 15-jan-90  1     1
# 3  01-jan-90 01-jan-90  1     1
# 4  01-jan-90 22-jan-90  1     1
# 5  01-jan-90 29-jan-90  1     1
# 6  01-jan-90 08-jan-90  1     2
# 7  01-jan-90 15-jan-90  1     2
# 8  01-jan-90 01-jan-90  1     2
# 9  01-jan-90 22-jan-90  1     2
# 10 01-jan-90 29-jan-90  1     2
# 11 01-jan-90 08-jan-90  1     3
# 12 01-jan-90 15-jan-90  1     3
# 13 01-jan-90 01-jan-90  1     3
# 14 01-jan-90 22-jan-90  1     3
# 15 01-jan-90 29-jan-90  1     3
# 16 02-jan-90 09-jan-90  2     1
# 17 02-jan-90 16-jan-90  2     1
# 18 02-jan-90 02-jan-90  2     1
# 19 02-jan-90 23-jan-90  2     1
# 20 02-jan-90 30-jan-90  2     1
# 21 02-jan-90 09-jan-90  2     2
# 22 02-jan-90 16-jan-90  2     2
# 23 02-jan-90 02-jan-90  2     2
# 24 02-jan-90 23-jan-90  2     2
# 25 02-jan-90 30-jan-90  2     2