R:根据多列中的值添加零行

问题描述 投票:0回答:3

我正在尝试将行附加到R data.frame。这是一个data.frame“ foo”的示例:

A   B   C   D
1   1   1   200
1   1   2   50
1   1   3   15
1   2   1   150
1   2   4   50
1   3   1   300
2   1   2   40
2   1   4   90
2   3   2   80

对于每个A,有3个可能的B值,对于每个B,有4个可能的C值。但是,初始df仅包含D的非零值。我想对df进行操作, B和C都包含零。因此,对于B / C的任何值为0,df都将在D中显示0。我见过用一列解决该问题的方法,但找不到解决该问题的方法多列。最终的df如下所示:

A   B   C   D
1   1   1   200
1   1   2   50
1   1   3   15
1   1   4   0
1   2   1   150
1   2   2   0
1   2   3   0
1   2   4   50
1   3   1   300
1   3   2   0
1   3   3   0
1   3   4   0
2   1   1   0
2   1   2   40
2   1   3   0
2   1   4   90
2   2   1   0
2   2   2   0
2   2   3   0
2   2   4   0
2   3   1   0
2   3   2   80
2   3   3   0
2   3   4   0

我首先尝试创建一个虚拟数据框,然后将其与初始df合并,但是某些方法无法正常工作。这是当前的代码,我知道这是错误的,因为该代码仅基于A生成行。我想我想基于A和B制作哑帧,但我不知道如何-if / else函数在这里可以工作?:

# create dummy df
dummy <- as.data.frame(
  cbind(
    sort(rep(unique(foo$A), 12)),
    rep(1:3,length(unique(foo$A)))))
colnames(dummy) <- c("A","B")
foo$A <- as.numeric(foo$A)
foo$B <- as.numeric(foo$C)

# merge with foo
mergedummy <- merge(dummy,foo,all.x=T)

非常感谢任何见识-谢谢!

r dataframe if-statement data-manipulation zero
3个回答
5
投票

一个衬板:

merge(dat, data.frame(table(dat[1:3]))[-4],all.y=TRUE)

#   A B C   D
#1  1 1 1 200
#2  1 1 2  50
#3  1 1 3  15
#4  1 1 4  NA
#...

或者也许不太复杂:

out <- data.frame(xtabs(D ~ ., data=dat))
out[do.call(order,out[1:3]),]

#   A B C Freq
#1  1 1 1  200
#7  1 1 2   50
#13 1 1 3   15
#19 1 1 4    0
#...

dat在哪里:

dat <- structure(list(A = c(1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L), B = c(1L, 
1L, 1L, 2L, 2L, 3L, 1L, 1L, 3L), C = c(1L, 2L, 3L, 1L, 4L, 1L, 
2L, 4L, 2L), D = c(200L, 50L, 15L, 150L, 50L, 300L, 40L, 90L, 
80L)), .Names = c("A", "B", "C", "D"), class = "data.frame", row.names = c(NA, 
-9L))

3
投票

我创建了一个主数据框,其中包含您在预期结果中描述的A,B和C的所有组合。然后,我合并主数据框架和您的数据框架。最后,我将NA替换为0。

master <- data.frame(A = rep(1:2, each = 12),
                     B = rep(1:3, each = 4),
                     C = rep(1:4, times = 6))

library(dplyr)

master %>%
    left_join(., mydf) %>%
    mutate(D = ifelse(D %in% NA, 0, D))

#   A B C   D
#1  1 1 1 200
#2  1 1 2  50
#3  1 1 3  15
#4  1 1 4   0
#5  1 2 1 150
#6  1 2 2   0
#7  1 2 3   0
#8  1 2 4  50
#9  1 3 1 300
#10 1 3 2   0
#11 1 3 3   0
#12 1 3 4   0
#13 2 1 1   0
#14 2 1 2  40
#15 2 1 3   0
#16 2 1 4  90
#17 2 2 1   0
#18 2 2 2   0
#19 2 2 3   0
#20 2 2 4   0
#21 2 3 1   0
#22 2 3 2  80
#23 2 3 3   0
#24 2 3 4   0

2
投票

这里是一种解决方案:

foo <- merge(expand.grid(lapply(foo[,1:3], unique)), foo, all=TRUE, sort=TRUE)
foo[is.na(foo)] <- 0
© www.soinside.com 2019 - 2024. All rights reserved.