【问题标题】:R How to loop over paired columns to create new columnsR如何循环配对列以创建新列
【发布时间】:2017-10-05 14:10:46
【问题描述】:

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

示例数据集:

    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&lt;-ifelse(df$s1&lt;=-3 &amp; df$st1&gt;=0, 1, 0)。最终目的是创建最终变量yes_no (1/0) 以指示列对之间的任何差异是否为 1,例如df$yes_no&lt;-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)
}

显然这行不通,但这就是我正在尝试的想法。 任何帮助,将不胜感激。

【问题讨论】:

    标签: r loops for-loop if-statement


    【解决方案1】:

    这里是基础 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 应用于配对元素(X 的第一个 elt 和 Y 的第一个元素等等..)

    3-rowSums 将 3 列聚合为一,>0 将其转换为逻辑向量

    【讨论】:

    • 谢谢,但有一个小错误,最后一列与我上面给出的略有不同?
    • @user63230 是的,但我已经使用了你的条件。
    • 只需要在 ifelse 语句中切换 i 和 r 即可: ifelse(df[[r]]=0, 1, 0)
    【解决方案2】:

    这是另一个使用 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
    

    【讨论】:

    • 很高兴帮助解决这个问题!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-04
    • 2011-05-22
    • 2022-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-10
    相关资源
    最近更新 更多