使用if将复制行压缩为唯一行

S31*_*S31 2 r 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
Run Code Online (Sandbox Code Playgroud)

结束目标

colNames      color   colorId
colB          Blue    22
colB          Red     40
colA          Red     40
colD          Red     40
colC          Red     40
None          Yellow  35
Run Code Online (Sandbox Code Playgroud)

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

我正在考虑编写一个函数,如果有多于0个colorId重复计数,则保留rowsu> 0的所有行,如果它们全部为0且整个rowsu = 0,则保留为特殊情况下为yellow.然后在所有重复项中保留一行,类似于下面的内容.(如果是问题,在编写此部分时遇到问题)

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
Run Code Online (Sandbox Code Playgroud)

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

Jaa*_*aap 5

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

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

这使:

    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
Run Code Online (Sandbox Code Playgroud)

这是做什么的:

  • setDT(dat)转换dat到一个"data.table"(这是一个的增强形式data.frame).
  • data.tble-syntax的作用类似dat[i, j, by](见1b的解释).在这种情况下,datcolorcolorId( - by = .(color, colorId)部分)分组.
  • 对于每个组,colSums(.SD == 1) > 0检查colAto colEcolums 是否包含a 1.生成的逻辑向量暂时存储为cs..SD代表D ata的S ubset (参见上一点链接中的2b).
  • 最后,我们检查至少有一列是否1sum(cs) > 0.如果是这种情况,则返回相应的列名names(.SD)[cs],如果条件不成立None则返回.

使用dplyrtidyverse你可以得到相同的结果有:

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