изменить несколько столбцов на основе условия и строки имени столбца - PullRequest
1 голос
/ 16 марта 2019

У меня очень редкий набор данных - ниже приведен пример формата.Я хочу внести изменения в конкретные столбцы, основываясь на логике, описанной ниже

# create dummy data set
pb=c('1','0','0','0','0','1','Not_ans','1','0','Not_ans')
qa=c('1','1','0','0','1','0','Not_ans','1','Not_ans','Not_ans')
#zy=c('1','Not_ans','0','1','Not_ans','0','1','1','1','Not_ans')

#sub questions for pb
pb.abr=c('1','0','0','0','0','1','0','1','0','0')
pb.ras=c('0','0','0','0','1','0','0','1','0','0')
pb.sfg=c('1','0','0','0','0','0','0','1','0','0')

#sub questions for qa
qa.fgs=c('1','0','0','0','0','0','0','1','0','0')
qa.sdf=c('0','1','0','0','0','0','0','0','0','0')
qa.tyu=c('0','0','0','0','1','0','0','1','0','0')

df=data.frame(pb,qa,pb.abr,pb.ras,pb.sfg,qa.fgs,qa.sdf,qa.tyu)
df

        pb      qa pb.abr pb.ras pb.sfg qa.fgs qa.sdf qa.tyu
1        1       1      1      0      1      1      0      0
2        0       1      0      0      0      0      1      0
3        0       0      0      0      0      0      0      0
4        0       0      0      0      0      0      0      0
5        0       1      0      1      0      0      0      1
6        1       0      1      0      0      0      0      0
7  Not_ans Not_ans      0      0      0      0      0      0
8        1       1      1      1      1      1      0      1
9        0 Not_ans      0      0      0      0      0      0
10 Not_ans Not_ans      0      0      0      0      0      0

Два столбца pb и qa называются базовыми столбцами, и у них есть дополнительные вложенные столбцы с соглашением об именах как pb.и QA.- таким образом, мы видим три подстолбца для pa и 3 для qa.Я хочу внести изменения в эти вложенные столбцы, основываясь на условии базового столбца (pa или qa).

Условие: если столбец pb =='Not_ans', тогда сделать все вложенные столбцы (pb.abr, pb.ras и pb.sfg) = 'Not_applicable'

как мне написать функцию, которая достигает этого?где я указываю базовое имя столбца, т.е. pb и наименование подколонок, пример 'pb.' ниже - будет ли это примерно так, как показано ниже, но это не даст результата

data.frame(ifelse(df['base_q']=='Not_ans',
df[ , grepl( paste('base_q','.') , names(df) )]=='Not_applicable',df[,grepl( 
paste('base_q','.') , names(df)) ])

Как мне написать обобщенную функциюкоторый принимает базовые номера столбцов в качестве входных данных для примера 1,2 здесь - применяет функцию, т. е. когда pb равен Not_ans, он меняет sub_columns (pb.abr, pb.ras, pb.sfg) на Неприменимо, а затем переходит к столбцу 2 (qa) и применяет ту же логику?

Ответы [ 3 ]

2 голосов
/ 16 марта 2019

Вы можете сделать с

yf=function(df,v){
   df[df[v]=='Not_ans',][,names(df)[substr(names(df),1,nchar(v)+1)==paste0(v,'.')]]='Not_applicable'
   return(df)
 }
yf(df,'pb')
        pb      qa         pb.abr         pb.ras         pb.sfg qa.fgs qa.sdf qa.tyu
1        1       1              1              0              1      1      0      0
2        0       1              0              0              0      0      1      0
3        0       0              0              0              0      0      0      0
4        0       0              0              0              0      0      0      0
5        0       1              0              1              0      0      0      1
6        1       0              1              0              0      0      0      0
7  Not_ans Not_ans Not_applicable Not_applicable Not_applicable      0      0      0
8        1       1              1              1              1      1      0      1
9        0 Not_ans              0              0              0      0      0      0
10 Not_ans Not_ans Not_applicable Not_applicable Not_applicable      0      0      0

Ввод данных

df=data.frame(pb,qa,pb.abr,pb.ras,pb.sfg,qa.fgs,qa.sdf,qa.tyu,stringsAsFactors = F) 
# notice stringsAsFactors 
0 голосов
/ 16 марта 2019

На основании ответа, данного @ Вэнь-Беном, сработал следующий код -

yf=function(df,v,y){ for(i in v:y) { df[df[i]=='Not_ans',][,names(df)[substr(names(df),1,nchar(colnames(df)[i])+1)==paste0(colnames(df)[i],'.')]]='Not_applicable' } return(df) }

0 голосов
/ 16 марта 2019

Один из способов будет следующим.Вы можете указать, к каким столбцам вы хотите применить функцию (или функции) в var в mutate_at().Здесь я использовал contains(), чтобы указать имена столбцов.Затем я заменил числовые значения в столбцах, когда pb == "Not_ans" на "Not_applicable".

mutate_at(df, 
          vars(contains("pb.")),
          .funs = funs(ifelse(pb == "Not_ans",
                              "Not_applicable",
                              .)))

#        pb      qa         pb.abr         pb.ras         pb.sfg qa.fgs qa.sdf qa.tyu
#1        1       1              2              1              2      1      0      0
#2        0       1              1              1              1      0      1      0
#3        0       0              1              1              1      0      0      0
#4        0       0              1              1              1      0      0      0
#5        0       1              1              2              1      0      0      1
#6        1       0              2              1              1      0      0      0
#7  Not_ans Not_ans Not_applicable Not_applicable Not_applicable      0      0      0
#8        1       1              2              2              2      1      0      1
#9        0 Not_ans              1              1              1      0      0      0
#10 Not_ans Not_ans Not_applicable Not_applicable Not_applicable      0      0      0

Если вы хотите применить одну и ту же задачу для pb и qa, вы можете использовать mutate_at() дважды.

mutate_at(df, 
          vars(contains("pb.")),
          .funs = funs(ifelse(pb == "Not_ans",
                              "Not_applicable",
                              .))) %>%
mutate_at(vars(contains("qa.")),
          .funs = funs(ifelse(qa == "Not_ans", "Not_applicable",.)))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...