R如何循环配对列以创建新列

时间:2017-10-05 14:10:47

标签: r loops for-loop if-statement

我试图遍历特定的对列(它们具有相似的名称)并根据条件语句创建列。

示例数据集:

    set.seed(2)
    df <- data.frame (id=rep(1:5),
                      s1=rnorm(5, 0, 3),
                      s2=rnorm(5, 0, 3),
                      s2a=rnorm(5, 0, 3),
                      st1=rnorm(5, 3, 3),
                      st2=rnorm(5, 3, 3),
                      st2a=rnorm(5, 3, 3))


> df
  id         s1         s2       s2a       st1        st2      st2a
1  1 -2.6907436  0.3972609  1.252952 -3.933207  9.2724576 -4.355119
2  2  0.5545476  2.1238642  2.945258  5.635814 -0.5997775  4.431712
3  3  4.7635360 -0.7190941 -1.178086  3.107420  7.7689146  1.210325
4  4 -3.3911270  5.9534218 -3.119007  6.038486  8.8639549  5.376610
5  5 -0.2407553 -0.4163610  5.346687  4.296795  3.0148133  3.868910

列s1与列st1等配对。如果这些列之间的相等性为-3到0,我想指示1/0。 df$ys1<-ifelse(df$s1<=-3 & df$st1>=0, 1, 0)。最终目标是创建最终变量yes_no(1/0)以指示列对之间的任何差异是否为1,例如df$yes_no<-ifelse(df$ys1==1 | df$ys2==1 | df$ys2a==1, 1, 0)

新数据集应如下所示:

> df
  id         s1         s2       s2a       st1        st2      st2a ys1 ys2 ys2a yes_no
1  1 -2.6907436  0.3972609  1.252952 -3.933207  9.2724576 -4.355119   0   0    0      0
2  2  0.5545476  2.1238642  2.945258  5.635814 -0.5997775  4.431712   0   0    0      0
3  3  4.7635360 -0.7190941 -1.178086  3.107420  7.7689146  1.210325   0   0    0      0
4  4 -3.3911270  5.9534218 -3.119007  6.038486  8.8639549  5.376610   1   0    1      1
5  5 -0.2407553 -0.4163610  5.346687  4.296795  3.0148133  3.868910   0   0    0      0

我确定有一种方法可以在不实际创建所有其他列的情况下进行循环(即只创建最后一列,yes_no)但我会对如何创建这些只是为了知道感兴趣怎么做,除了更简洁的方法。 我认为一种方法是将数据集分成两组,然后在循环中使用:

firstt<-(df[,c(2:4)])
final<-(df[,c(5:7)])

或跳过它并直接尝试循环

for(i in names(df[,c(2:4)])){
r<-(df[,c(5:7)])
df[i] <-ifelse(df$[i]<=-3 & df$[r]>=0, 1, 0)
}
显然,这不会起作用,但这就是我尝试的想法。 任何帮助,将不胜感激。

2 个答案:

答案 0 :(得分:2)

这里是基础R的解决方案:

df$yes_no <- 
  rowSums(mapply(function(i,r)
    ifelse(df[[r]]<=-3 & df[[i]]>=0, 1, 0)
  ,  grep("st",names(df),value=TRUE),
  gsub("t","",grep("st",names(df),value=TRUE))))  >0

1-我正在使用正则表达式来提取名称。你也可以在这里使用索引。 $ X

X = "st1"  "st2"  "st2a"

Y = "s1"  "s2"  "s2a"

2-我正在使用mapply申请成对的elemend(X的第一个元素和Y的第一个元素等等)。

3- rowSums将3列聚合在一起,&gt; 0将其转换为逻辑向量

答案 1 :(得分:1)

以下是for循环的另一种解决方案

a <- names(df[,c(2:4)])
b <- names(df[,c(5:7)])
for(i in seq_along(a)){
df$temp<-ifelse(df[,names(df)[names(df)==a[i]]]<=-3 & df[,names(df)[names(df)==b[i]]]>=0, 1, 0)
names(df)[names(df)=="temp"] <- paste0("ys", i)
}

df$yes_no <- apply(df[grep("ys", names(df))]==1,1,  function(k) ifelse(TRUE %in% k, 1, 0) )

print(df)
  id         s1         s2       s2a       st1        st2      st2a ys1 ys2 ys3 yes_no
1  1 -2.6907436  0.3972609  1.252952 -3.933207  9.2724576 -4.355119   0   0   0      0
2  2  0.5545476  2.1238642  2.945258  5.635814 -0.5997775  4.431712   0   0   0      0
3  3  4.7635360 -0.7190941 -1.178086  3.107420  7.7689146  1.210325   0   0   0      0
4  4 -3.3911270  5.9534218 -3.119007  6.038486  8.8639549  5.376610   1   0   1      1
5  5 -0.2407553 -0.4163610  5.346687  4.296795  3.0148133  3.868910   0   0   0      0