根据具有不同名称的行重命名列中的所有行

时间:2018-03-02 18:30:20

标签: r dataframe dplyr rows r-factor

我有一个这样的数据框:

 df <- setNames(data.frame(matrix(c(rep(1,8),c(1,2,3,1,2,3,4,1),
                               rep("useless",3),"label1",
                               rep("useless",3),"label2",
                               floor(runif(8,100,400))),8,4)),
                               c("subject","trial","block","data"))

     subject trial   block data
   1       1     1 useless  144
   2       1     2 useless  380
   3       1     3 useless  118
   4       1     1  label1  323
   5       1     2 useless  250
   6       1     3 useless  292
   7       1     4 useless  375
   8       1     1  label2  358

我想把所有“无用的”行放到它们之后的“标签”行中。

输出:

   subject trial   block data
 1       1     1  label1  144
 2       1     2  label1  380
 3       1     3  label1  118
 4       1     1  label1  323
 5       1     2  label2  250
 6       1     3  label2  292
 7       1     4  label2  375
 8       1     1  label2  358

我正在考虑这些问题,但不知道该怎么做:

 df %>%
   mutate(block = ifelse(block == "useless", "make it the end label", block))

我知道必须有一个非常简单的解决方案,但我没有看到它。我更喜欢tidyverse的答案,但会接受任何有用的答案。

2 个答案:

答案 0 :(得分:3)

useless值替换为NA,然后执行向后填充:

library(tidyverse)
df %>% 
    mutate(block = ifelse(grepl('label', block), as.character(block), NA)) %>% 
    fill(block, .direction = 'up')

#  subject trial  block data
#1       1     1 label1  108
#2       1     2 label1  391
#3       1     3 label1  201
#4       1     1 label1  239
#5       1     2 label2  332
#6       1     3 label2  239
#7       1     4 label2  363
#8       1     1 label2  267

如果您只有一个无用的值,请使用na_if

library(tidyverse)
df %>% 
    mutate(block = na_if(block, 'useless')) %>% 
    fill(block, .direction = 'up')

#  subject trial  block data
#1       1     1 label1  108
#2       1     2 label1  391
#3       1     3 label1  201
#4       1     1 label1  239
#5       1     2 label2  332
#6       1     3 label2  239
#7       1     4 label2  363
#8       1     1 label2  267

答案 1 :(得分:2)

基础R解决方案将是:

df$block <- ave(
    df$block, rev(cumsum(rev(df$block != 'useless'))),
    FUN = function(x) x[length(x)])

df
#   subject trial  block data
# 1       1     1 label1  138
# 2       1     2 label1  380
# 3       1     3 label1  376
# 4       1     1 label1  111
# 5       1     2 label2  124
# 6       1     3 label2  231
# 7       1     4 label2  215
# 8       1     1 label2  361