How to copy value of a cell to other rows based on

2020-07-25 01:13发布

I have a data frame that looks like this:

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)

The desirable result is to have the value under "Answer" (0 or 1) copied to the NA cells of the same Subject and the same Item. For instance, the answer = 0 in row 2 should be copied to the answer cell in row 1, but not other rows. The output should be like this:

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)

How should I do this? I noticed that there are some previous questions that asked how to copy a cell to other cells such as replace NA value with the group value, but it was done based on the value of one column only. Also, this question is slightly different from Replace missing values (NA) with most recent non-NA by group, which aims to copy the most-recent numeric value to NAs.

Thanks for all your answers!

标签: r
3条回答
唯我独甜
2楼-- · 2020-07-25 01:38

Though it was not intention of OP but I thought of situations where there are only NA values for set of Sub, Item group OR there multiple non-NA values for a group.

The one way to handle such situations could be by taking max/min of that group and ignoring max/min values if those are Inf

A solution could be:

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
查看更多
三岁会撩人
3楼-- · 2020-07-25 01:45

You can use 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

Thanks to @steveb, here is an alternative without having to rely on zoo::na.locf:

Data %>% group_by(Sub, Item) %>% mutate(Answer = Answer[!is.na(Answer)]);
查看更多
祖国的老花朵
4楼-- · 2020-07-25 01:48
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
查看更多
登录 后发表回答