如何根据其他两列的值将单元格的值复制到其他行?

时间:2018-02-22 05:26:55

标签: r

我有一个如下所示的数据框:

zz = "Sub Item Answer
1      A   1    NA
2      A   1    0
3      A   2    NA
4      A   2    1
5      B   1    NA
6      B   1    1
7      B   2    NA
8      B   2    0"    
Data = read.table(text=zz, header = TRUE)

理想的结果是将“答案”(0或1)下的值复制到相同主题和相同项目的NA单元格中。例如,第2行中的answer = 0应该被复制到第1行的应答单元格,而不是其他行。输出应该是这样的:

zz2 = "Sub Item Answer
1      A   1    0
2      A   1    0
3      A   2    1
4      A   2    1
5      B   1    1
6      B   1    1
7      B   2    0
8      B   2    0"
Data2 = read.table(text=zz2, header = TRUE)

我该怎么做?我注意到之前有一些问题询问如何将单元格复制到其他单元格,例如replace NA value with the group value,但它仅基于一列的值完成。此外,这个问题与Replace missing values (NA) with most recent non-NA by group略有不同,https://codepen.io/vijayrkumar/pen/JpZROy旨在将最新的数值复制到NA。

感谢您的所有答案!

3 个答案:

答案 0 :(得分:2)

您可以使用zoo::na.locf

library(tidyverse);
library(zoo);
Data %>% group_by(Sub, Item) %>% mutate(Answer = na.locf(Answer));
# A tibble: 8 x 3
## Groups:   Sub, Item [4]
#  Sub    Item Answer
#  <fct> <int>  <int>
#1 A         1      0
#2 A         1      0
#3 A         2      1
#4 A         2      1
#5 B         1      1
#6 B         1      1
#7 B         2      0
#8 B         2      0

感谢@steveb,这里有一个替代方案,而不必依赖zoo::na.locf

Data %>% group_by(Sub, Item) %>% mutate(Answer = Answer[!is.na(Answer)]);

答案 1 :(得分:0)

library(tidyverse)
Data%>%group_by(Sub,Item)%>%fill(Answer,.direction = "up")
# A tibble: 8 x 3
# Groups:   Sub, Item [4]
     Sub  Item Answer
  <fctr> <int>  <int>
1      A     1      0
2      A     1      0
3      A     2      1
4      A     2      1
5      B     1      1
6      B     1      1
7      B     2      0
8      B     2      0

答案 2 :(得分:0)

虽然不是OP的意图,但我想到的情况是NA组的集合只有Sub, Item值,或者组中有多个非NA值。

处理此类情况的一种方法可能是取max/min该组,忽略max/min值,如果这些值为Inf

解决方案可能是:

library(dplyr)
Data %>% group_by(Sub, Item) %>% 
    mutate(Answer = ifelse(max(Answer, na.rm=TRUE)== -Inf, NA, 
                     as.integer(max(Answer, na.rm=TRUE))))

#Result
#  Sub     Item Answer
#  <fctr> <int>  <int>
#1 A          1      0
#2 A          1      0
#3 A          2      1
#4 A          2      1
#5 B          1      1
#6 B          1      1
#7 B          2      0
#8 B          2      0