如何编写循环或函数来获取具有数据帧重复值的矩阵?

时间:2016-10-25 22:21:19

标签: r function dataframe rep

我正在尝试从另一个数据帧获取数据帧,执行某些值(在我的示例中为a,b,c和d)重复一定次数(其值出现在我的第一个数据帧的每个单元格中) 。为了更好地说明这一点,我展示了数据:

df<-data.frame(replicate(4,sample(20:50,10,rep=TRUE)))
a<-0
b<-1
c<-2
d<-9

我先试了一下:

for (i in 1:10)
{
print(rep(a, df[i,1]))
}

但是当我试图保存输出时,它只给我第一行分析:

for (i in 1:10)
{
output<-print(rep(a, df[i,1]))
}

然后我尝试了一些比较复杂的东西:

myfunc<-function(n){
  a<-0
  b<-1
  c<-2
  d<-9
  IDs<- matrix(n[,1]) #A new column with the IDs for each row(rownames)
  w = NULL
  x = NULL
  y = NULL
  z = NULL
  for (i in 1:nrow(n)) {
    w<-rbind(t(as.matrix(rep(a, n[i,1]))))
    x<-rbind(t(as.matrix(rep(b, n[i,2]))))
    y<-rbind(t(as.matrix(rep(c, n[i,3]))))
    z<-rbind(t(as.matrix(rep(d, n[i,4]))))
  }
  output<-cbind(IDs, w, x, y, z)
  return(output <- as.data.frame(output))
}

但我没有得到我需要的东西。

对于这样的矩阵:

Example matrix

预期输出为:

第一行:21次0,46次1次,25次2次和28次9.全部在120列......依此类推其他行

如果你能帮助我解决这个问题,我真的很感激。

2 个答案:

答案 0 :(得分:1)

如果我理解正确,从for循环移动到lapply可以得到你想要的东西。

 lapply(1:10, function(i) rep(a, df[i, 1]))

然后,您可以通过

对所有列进行概括
l <- list(a = 0, b = 1, c = 2, d = 9)
lapply(seq_along(l), function(i) lapply(1:10, function(j) rep(l[[i]], df[j, i])))

它为您提供了一个嵌套列表和(我认为)您想要的输出。

修改

现在我更了解你想要什么,我想我可以帮助更好。但在我看来,你有一个问题,你想要一个矩阵,但至少在你提供的例子中,矩阵的每一行都有不同的长度。我没有用NA填充这些内容,而是创建了第五列,将事情弄平了。看看下面是否有你想要的东西。

df$X5 <- (max(rowSums(df)) + 5) - rowSums(df)

l <- list(a = 0, b = 1, c = 2, d = 9, e = 5)

tmp <- lapply(seq_along(l), function(i) {
    lapply(1:nrow(df), function(j) rep(l[[i]], df[j, i]))
})

max_col <- max(rowSums(df))

m <- matrix(rep(NA, length(l)*max_col), ncol = max_col)

for(i in seq_along(l)) {
    m[i, ] <- unlist(lapply(tmp, "[[", i))
}

答案 1 :(得分:0)

我认为你对矩阵第一行的期望是

r1 <- rep(c(0, 1, 2, 9), times=c(21, 46, 25, 28))

从第二行开始

r2 <- rep(c(0, 1, 2, 9), times=c(47, 46, 45, 46))

如果是这样,那么如果你想将它放入数据框中,你就会遇到长度不等的问题。

length(r1)
# [1] 120

length(r2)
# [1] 184

数据框无法处理,但列表

l <- list(r1, r2)

要对矩阵中的所有行执行此操作,您可以执行类似

的操作
mat <- matrix(c(21, 46, 25, 28,
                47, 46, 45, 46,
                35, 24, 46, 42,
                27, 22, 36, 50), 4, byrow=TRUE)

l <- list()

for (row in 1:4) {
    l[[row]] <- rep(c(0, 1, 2, 9), times=c(mat[row, 1], mat[row, 2], 
                                           mat[row, 3], mat[row, 4]))
}

sapply(l, length)
# [1] 120 184 147 135

我不知道0 1 2 9来自哪里,如果它有所不同,你也必须将其考虑在内。如果实际矩阵中有更大或不同数量的列,那么你可能会更好地使用嵌套循环或丹尼尔建议的一些lapply魔法。

如果你真的想要一个矩阵/数据帧类型结构,你可以通过填充NA来获得它,例如像这样

mat.new <- t(sapply(l, '[', seq(max(sapply(l, length)))))