R:比较多个列对并将值放在新的对应变量上

时间:2018-08-23 10:11:23

标签: r

是基本的R用户。

在同一数据框中,每个“ id ”有50个列对(示例对为:“ pair_q1 ”和“ pair_01_v_rde ”)我想从中收集数据并将其放在新的相应变量中,例如“ newvar_q1 ”。

所有对变量名的名称中都有一个模式,可以将其提炼为此(“ pair_qX”和“ pair_X_v_rde ”,其中X = 1:50,以及我想要的最终变量具有“ newvar_qX ”,其中X = 1:50)

理想情况下,该对中只有一个成员应包含数据,但事实并非如此。

每个变量可以包含1:5或NA(缺失)的值。

基于“ id ”从每对数据收集数据的规则以及在它们新创建的对应变量中放置的内容是:

如果其中一对具有值,而另一对缺失,则将值放入其对应的新变量中。例如(“ pair_q1 ” = 1且“ pair_01_v_rde ” = NA,然后“ newvar_q1 ” = 1)

如果两对值相同或都缺失,则将该值/缺失值放在其对应的新变量中,例如(“ pair_q50 ” = 1 / NA,而“ pair_50_v_rde ” = 1 / NA,然后“ newvar_q50 ” = 1 / NA)

如果两个对都有不同的值,则忽略两个值,并为其分配对应的新变量999,例如(“ pair_q02 ” = 3,而“ pair_02_v_rde ” = 2则“ newvar_q02 ” = 999)

有人可以告诉我如何在R中执行此操作吗?

谢谢! 妮莉

# Create Toy dataset
id <- c(100, 101, 102)
pair_q1 <- c(1, NA, 1)
pair_01_v_rde <- c(NA, 2, 1)
pair_q2 <- c(1, 1, NA)
pair_02_v_rde <- c(2, NA, NA)
pair_q50 <- c(NA, 2, 4)
pair_50_v_rde <- c(4, 3, 1)

mydata <- data.frame(id, pair_q1, pair_01_v_rde, pair_q2, pair_02_v_rde, pair_q50, pair_50_v_rde)


# The dataset
> mydata
id pair_q1 pair_01_v_rde pair_q2 pair_02_v_rde pair_q50 pair_50_v_rde
1 100       1            NA       1             2       NA             4
2 101      NA             2       1            NA        2             3
3 102       1             1      NA            NA        4             1


# Here I manually build what I would like to have in the dataset 
newvar_q1 <- c(1, 2, 1)
newvar_q2 <- c(999, 1, NA)
newvar_q50 <- c(4, 999, 999)


mydata2 <- data.frame(id, pair_q1, pair_01_v_rde, pair_q2, pair_02_v_rde, pair_q50, pair_50_v_rde, newvar_q1, newvar_q2, newvar_q50)

> mydata2

id pair_q1 pair_01_v_rde pair_q2 pair_02_v_rde pair_q50 pair_50_v_rde newvar_q1 newvar_q2 newvar_q50
1 100       1            NA       1             2       NA             4         1       999          4
2 101      NA             2       1            NA        2             3         2         1        999
3 102       1             1      NA            NA        4             1         1        NA        999

1 个答案:

答案 0 :(得分:0)

使用'tidyverse'的可能解决方案(使用'inner_join(mydata,。,by =“ id”)'以问题中给出的顺序获取新列):

mydata %>% 
  select(id,matches("^pair_q")) %>%                  # keeps only left part of pairs
  gather(k,v1,-id) %>%                               # transforms into tuples (id,variable name,variable value)
  mutate(n=as.integer(str_extract(k,"\\d+"))) -> df1 # converts variable name into variable number
mydata %>% 
  select(id,matches("^pair_\\d")) %>%                # same on right part of pairs 
  gather(k,v2,-id) %>% 
  mutate(n=as.integer(str_extract(k,"\\d+"))) -> df2

inner_join(df1,df2,by=c("id","n")) %>% 
  mutate(w=case_when(is.na(v1) ~ v2,      # builds new variable value
                     is.na(v2) ~ v1,      # from your rules
                     v1==v2 ~ v1,
                     TRUE ~999),
        k=paste0("newvar_q",n)) %>%        # builds new variable name from variable number
  select(id,k,w) %>%                       # keeps only useful columns
  spread(k,w) %>%                          # switches back from tuple view to wide view 
  inner_join(mydata,by="id")               # and merges the new variables to the original data

#   id newvar_q1 newvar_q2 newvar_q50 pair_q1 pair_01_v_rde pair_q2 pair_02_v_rde pair_q50 pair_50_v_rde
#1 100         1       999          4       1            NA       1                 #2       NA             4
#2 101         2         1        999      NA             2       1            NA        2             3
#3 102         1        NA        999       1             1      NA            NA        4             1