2017-02-13 3 views
2

同じ接頭辞で始まる他の列に値が存在する場合、どの列のNAをすべて0に置き換えるのですか?たとえば、列A1の場合、列A2またはA3がNONBLANKの場合は、NAを0に置き換えます。私の実際のデータには何百もの列があります。列グループ接頭辞に基づいて列グループの空白を置き換える方法は?

MY DATA:

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) 

があります

enter image description here

がWANTED:

0列A1にNAを交換する必要があり、列A2またはA3の場合ハ enter image description here

+0

私は会議に出かける必要があるので部分的な答えがありますが、あなたはmydata [!is.na(mydata [c( 'A1'、 'A2')])を使って、 –

答えて

3

ベースRで非洗練された答えが、動作しているようです:

1. A 0は列A1またはA3には1を持っている場合は、列A2にNAを交換する、というように、以下のようにする必要がありまし
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 
} 

います:

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 

編集:
アイデアがunique手紙Fを抽出することであるがこの例では、数字(\\d)を空白の""に置き換えることによって、colnames(mydata),AおよびBを入力します。
次に、これらの文字をループして開始する列を選択します。それはgrepl(i,colnames(mydata))のことです。
applyは、少なくとも1つの非NA値(!is.na()):apply(mydata[,grepl(i,colnames(mydata))],1,function(x) any(!is.na(x)))が少なくとも(any())ある行のベクトルを得るために使用されます。
すべては本質的にdf[is.na(df))]<-0で結合されますが、dfは、指定された文字を含む列に対応し、NAを置き換えた行に対応します。
dfは次のようになります。mydata[apply(mydata[,grepl(i,colnames(mydata))],1,function(x) any(!is.na(x))),grepl(i,colnames(mydata))]

+0

これを読みやすくするには、いくつかの水平と垂直の空白を編集する必要があります。 – alistaire

4

もう一つの方法は、

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 

ある列の値がそうする@ haborymeの技術以下、あなたが

を行うことができ、多くのグループと便利されていない、ハードコーディングされています
# group columns into list elements with lapply and grep 
myCols <- lapply(c("A", "B"), function(i) grep(i, colnames(mydata))) 

# loop through and make changes 
for(i in myCols) { 
    mydata[, i][is.na(mydata[, i])] <- rep(NA^(rowSums(is.na(mydata[i])) == 3) - 1, 
             length(i))[is.na(mydata[, i])] 
} 
4

カスタマイズされた機能を使用してlapply():単一のアルファベットを有するこのパターンに従うと提供される列の数

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 
2

2つのオプションがあります。より実用的なものは、実際のデータの寸法に依存します。どちらも条件付きで​​3210を活用します。

手動:

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 

プレフィックスは、例えば、単一の文字を超えて、適切な正規表現でsubstrを置き換えることができた場合sub('\\d+$', '', var)

関連する問題