R 如何根据列组前缀替换列组的空格?

R 如何根据列组前缀替换列组的空格?,r,replace,na,prefix,R,Replace,Na,Prefix,如何根据以相同前缀开头的其他列中是否存在值,将列中的NA替换为所有0?例如,对于列A1,我只想将NA替换为0,其中列A2或A3为非空。我的真实数据有数百组列 我的数据: ID<-c(1,2,3,4,5,6,7,8) A1<-c(1,NA,1,NA,1,1,1,NA) A2<-c(1,NA,NA,1,NA,1,NA,NA) A3<-c(1,NA,NA,NA,1,NA,NA,NA) B1<-c(1,1,1,1,1,1,NA,1) B2<-c(1,1,1,1,NA,

如何根据以相同前缀开头的其他列中是否存在值,将列中的NA替换为所有0?例如,对于列A1,我只想将NA替换为0,其中列A2或A3为非空。我的真实数据有数百组列

我的数据:

ID<-c(1,2,3,4,5,6,7,8)
A1<-c(1,NA,1,NA,1,1,1,NA)
A2<-c(1,NA,NA,1,NA,1,NA,NA)
A3<-c(1,NA,NA,NA,1,NA,NA,NA)
B1<-c(1,1,1,1,1,1,NA,1)
B2<-c(1,1,1,1,NA,1,NA,NA)
B3<-c(1,1,NA,NA,1,NA,NA,NA)

mydata<-cbind.data.frame(ID,A1,A2,A3,B1,B2,B3)

IDbase
R
中的非精确答案,但似乎有效:

for(i in unique(gsub("\\d","",colnames(mydata)[-1]))){
  mydata[apply(mydata[,grepl(i,colnames(mydata))],1,function(x) any(!is.na(x))),grepl(i,colnames(mydata))][is.na(mydata[apply(mydata[,grepl(i,colnames(mydata))],1,function(x) any(!is.na(x))),grepl(i,colnames(mydata))])]<-0
}
编辑:
其思想是通过将数字(
\\d
)替换为空白的

然后循环这些字母以选择以其开头的列。这就是grepl(i,colnames(mydata))
所做的。
apply
用于获取行向量,其中至少有(
any()
)一个非NA值(
!is.NA()
):
apply(mydata[,grepl(i,colnames(mydata))],1,函数(x)any(!is.NA(x))
然后,所有的东西都被组合在它本质上的
df[is.na(df))]另一种方法是

mydata[, 2:4][is.na(mydata[, 2:4])] <- rep(NA^(rowSums(is.na(mydata[2:4])) == 3) - 1,
                                           length(2:4))[is.na(mydata[, 2:4])]
mydata[, 5:7][is.na(mydata[, 5:7])] <- rep(NA^(rowSums(is.na(mydata[5:7])) == 3) - 1,
                                           length(5:7))[is.na(mydata[, 5:7])]

mydata
  ID A1 A2 A3 B1 B2 B3
1  1  1  1  1  1  1  1
2  2 NA NA NA  1  1  1
3  3  1  0  0  1  1  0
4  4  0  1  0  1  1  0
5  5  1  0  1  1  0  1
6  6  1  1  0  1  1  0
7  7  1  0  0 NA NA NA
8  8 NA NA NA  1  0  0

mydata[,2:4][is.na(mydata[,2:4])]一个使用
lappy()
的自定义函数:通用为具有任意数量的列,前提是它们遵循具有单个字母的模式

func <- function(x){
  df <- mydata[grepl(x, colnames(mydata))] # extract only the same letter columns
  m <- !is.na(df)          # create a logical matrix to know which all are NA's
  i = which(rowSums(m)!=0) # if all had NA's then summ will be 0. so avoid that
  df[i,][is.na(df[i,])] <- 0 # insert wherever NA's to be 0( but only in those rows decided above)
  return(df)
  }

data.frame(ID = mydata$ID,lapply(LETTERS[1:2], func))
#  ID A1 A2 A3 B1 B2 B3
#1  1  1  1  1  1  1  1
#2  2 NA NA NA  1  1  1
#3  3  1  0  0  1  1  0
#4  4  0  1  0  1  1  0
#5  5  1  0  1  1  0  1
#6  6  1  1  0  1  1  0
#7  7  1  0  0 NA NA NA
#8  8 NA NA NA  1  0  0

func两个tidyverse选项;哪个更实用取决于实际数据的维度。两者都有条件地结合

手动:

library(tidyverse)

mydata %>% rowwise() %>%    # group by row
    mutate_at(vars(starts_with('A')),    # for A prefixes, coalesce if not all NA
              funs(ifelse(all(is.na(c(A1, A2, A3))), ., coalesce(., 0)))) %>% 
    mutate_at(vars(starts_with('B')),    # likewise for B
              funs(ifelse(all(is.na(c(B1, B2, B3))), ., coalesce(., 0))))

## Source: local data frame [8 x 7]
## Groups: <by row>
## 
## # A tibble: 8 × 7
##      ID    A1    A2    A3    B1    B2    B3
##   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1     1     1     1     1     1     1     1
## 2     2    NA    NA    NA     1     1     1
## 3     3     1     0     0     1     1     0
## 4     4     0     1     0     1     1     0
## 5     5     1     0     1     1     0     1
## 6     6     1     1     0     1     1     0
## 7     7     1     0     0    NA    NA    NA
## 8     8    NA    NA    NA     1     0     0
库(tidyverse)
mydata%%>%rowwise()%%>%#按行分组
变异_at(vars(以('A')开头),对于A前缀,如果不是全部NA,则合并
funs(ifelse(all(is.na(c(A1,A2,A3)),,coalesce(,0)))%>%
在(vars)(以('B')开头)处变异,对于B也是如此
funs(ifelse(all(is.na(c(B1,B2,B3)),,coalesce(,0)))
##来源:本地数据帧[8 x 7]
##小组:
## 
###A tibble:8×7
##ID A1 A2 A3 B1 B2 B3
##         
## 1     1     1     1     1     1     1     1
##2不,不,不,不
## 3     3     1     0     0     1     1     0
## 4     4     0     1     0     1     1     0
## 5     5     1     0     1     1     0     1
## 6     6     1     1     0     1     1     0
##771010NA NA NA NA
##8NA NA 10 0 0
或以编程方式,通过重塑:

mydata %>% gather(var, val, -ID) %>%    # reshape to long
    group_by(ID, letter = substr(var, 1, 1)) %>%    # group by ID and prefix
    mutate(val = if(all(is.na(val))) val else coalesce(val, 0)) %>% 
    ungroup() %>% select(-letter) %>% spread(var, val)    # clean up

## # A tibble: 8 × 7
##      ID    A1    A2    A3    B1    B2    B3
## * <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1     1     1     1     1     1     1     1
## 2     2    NA    NA    NA     1     1     1
## 3     3     1     0     0     1     1     0
## 4     4     0     1     0     1     1     0
## 5     5     1     0     1     1     0     1
## 6     6     1     1     0     1     1     0
## 7     7     1     0     0    NA    NA    NA
## 8     8    NA    NA    NA     1     0     0
mydata%%>%gather(var,val,-ID)%%>%#重新整形为long
分组依据(ID,字母=substr(var,1,1))%>%#分组依据ID和前缀
突变(val=if(all(is.na(val)))val-else结合(val,0))%>%
解组()%%>%select(-letter)%%>%spread(var,val)#清理
###A tibble:8×7
##ID A1 A2 A3 B1 B2 B3
## *       
## 1     1     1     1     1     1     1     1
##2不,不,不,不
## 3     3     1     0     0     1     1     0
## 4     4     0     1     0     1     1     0
## 5     5     1     0     1     1     0     1
## 6     6     1     1     0     1     1     0
##771010NA NA NA NA
##8NA NA 10 0 0

如果前缀可以扩展到一个字母以外,请使用合适的正则表达式替换
substr
,例如
sub('\\d+$,'',var)

部分答案,因为我必须赶去参加会议,但您可以使用:mydata[!is.na(mydata[c('A1','A2'))索引A1和A2中未丢失的值您应该编辑一些水平和垂直空白,以使其更具可读性。
library(tidyverse)

mydata %>% rowwise() %>%    # group by row
    mutate_at(vars(starts_with('A')),    # for A prefixes, coalesce if not all NA
              funs(ifelse(all(is.na(c(A1, A2, A3))), ., coalesce(., 0)))) %>% 
    mutate_at(vars(starts_with('B')),    # likewise for B
              funs(ifelse(all(is.na(c(B1, B2, B3))), ., coalesce(., 0))))

## Source: local data frame [8 x 7]
## Groups: <by row>
## 
## # A tibble: 8 × 7
##      ID    A1    A2    A3    B1    B2    B3
##   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1     1     1     1     1     1     1     1
## 2     2    NA    NA    NA     1     1     1
## 3     3     1     0     0     1     1     0
## 4     4     0     1     0     1     1     0
## 5     5     1     0     1     1     0     1
## 6     6     1     1     0     1     1     0
## 7     7     1     0     0    NA    NA    NA
## 8     8    NA    NA    NA     1     0     0
mydata %>% gather(var, val, -ID) %>%    # reshape to long
    group_by(ID, letter = substr(var, 1, 1)) %>%    # group by ID and prefix
    mutate(val = if(all(is.na(val))) val else coalesce(val, 0)) %>% 
    ungroup() %>% select(-letter) %>% spread(var, val)    # clean up

## # A tibble: 8 × 7
##      ID    A1    A2    A3    B1    B2    B3
## * <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1     1     1     1     1     1     1     1
## 2     2    NA    NA    NA     1     1     1
## 3     3     1     0     0     1     1     0
## 4     4     0     1     0     1     1     0
## 5     5     1     0     1     1     0     1
## 6     6     1     1     0     1     1     0
## 7     7     1     0     0    NA    NA    NA
## 8     8    NA    NA    NA     1     0     0