使用if

时间:2018-02-07 07:38:15

标签: r dataframe conditional-statements

所以有这样的情况:

DataFrame:

dat <- data.frame(colA = rep(c(0,1,0), c(6,1,8)), 
                  colB = rep(c(1,0,1,0), c(1,4,1,9)), 
                  colC = rep(c(0,1,0), c(9,1,5)), 
                  colD = rep(c(0,1,0), c(8,1,6)), 
                  colE = rep(0, 15), 
                  color = rep(c("blue","red","yellow"), each=5), 
                  colorId = rep(c(22,40,35), each=5))

colA   colB    colC    colD   colE   color   colorId
0      1       0       0      0      Blue    22
0      0       0       0      0      Blue    22
0      0       0       0      0      Blue    22
0      0       0       0      0      Blue    22
0      0       0       0      0      Blue    22
0      1       0       0      0      Red     40
1      0       0       0      0      Red     40
0      0       0       0      0      Red     40
0      0       0       1      0      Red     40
0      0       1       0      0      Red     40
0      0       0       0      0      Yellow  35
0      0       0       0      0      Yellow  35
0      0       0       0      0      Yellow  35
0      0       0       0      0      Yellow  35
0      0       0       0      0      Yellow  35

结束目标

colNames      color   colorId
colB          Blue    22
colB          Red     40
colA          Red     40
colD          Red     40
colC          Red     40
None          Yellow  35

这是我开始采取的方法,然后质疑自己陷入混乱。下面没有显示,我创建了另一个列,它使用rowSums(dat $ rowsu&lt; - rowSums(dat [1:4] == 1))对'col'列的二进制值求和。

我正在考虑编写一个函数,如果有多个colorId重复计数,那么保留rowsu&gt;的所有行。 0,在特殊情况下为黄色,如果它们全部为0且整个rowsu = 0,那么只需在所有重复项中保留一行,类似于下面的内容。 (虽然这是问题,但在编写这部分时遇到了麻烦)

colA   colB    colC    colD   colE   color   colorId
0      1       0       0      0      Blue    22
0      1       0       0      0      Red     40
1      0       0       0      0      Red     40
0      0       0       1      0      Red     40
0      0       1       0      0      Red     40
0      0       0       0      0      Yellow  35

其次,对于后一个使用名称创建列的问题,还在考虑一个if函数,如果它的下面有1,那么使用colname名称将其提取到行名中?不确定。

2 个答案:

答案 0 :(得分:5)

使用data.table - 包的可能解决方案:

library(data.table)
setDT(dat)[, .(colNames = {cs <- colSums(.SD == 1) > 0;
                           if(sum(cs) > 0) names(.SD)[cs] else 'None'})
           , by = .(color, colorId)]

给出:

    color colorId colNames
1:   blue      22     colB
2:    red      40     colA
3:    red      40     colB
4:    red      40     colC
5:    red      40     colD
6: yellow      35     None

这是做什么的:

  • setDT(dat)dat转换为&#39; data.table&#39; (这是 data.frame )。
  • data.tble - 语法与dat[i, j, by] (see 1b for an explanation)类似。在这种情况下,datcolorcolorIdby = .(color, colorId) - 部分)进行分组。
  • 对于每个组,colSums(.SD == 1) > 0会检查colAcolE列中是否包含1。生成的逻辑向量暂时存储为cs.SD代表 D ata的 S ubset(请参阅上一点中链接下方的2b)。
  • 最后,我们检查其中至少有一列是否1 sum(cs) > 0。如果是这种情况,则names(.SD)[cs]会返回相应的列名,如果条件未保留None则会返回。

使用dplyr中的tidyverse,您可以获得相同的结果:

library(dplyr)
dat %>% 
  group_by(color, colorId) %>% 
  do(data.frame(colNames = {cs <- colSums(. == 1) > 0;
                            if(sum(cs) > 0) names(.)[cs] else 'None'}))

答案 1 :(得分:0)

以下是tidyverse的一个选项,其中我们gather列'colA'到'colE'为长格式,按'color','colorId'分组,创建'None'为'' colNames'if所有'val'都是0.获取distinct行和filter获取'val'为1或'colNames'为'None'和{{1}的行感兴趣的列和select如果需要

arrange