将观察值移到不同的行

时间:2020-08-02 18:57:40

标签: r

例如

我有这个数据框:

a 1 2 3 4 5 6
b 7 8 9 1 2 3
c 4 5 6 7 8 9 

,我想将其转换为:

a 1 2 3
a 4 5 6
b 7 8 9
b 1 2 3
c 4 5 6
c 7 8 9

基本上,对于每一行,我都希望例如第2到第6,第7到第11,第11到第15 ......可变值将行移动到下面,第一个可变值是原始行的字母。

我该怎么办?我试图与collect()一起工作,但事实并非如此。 我只是R语言的初学者,希望能对您有所帮助。谢谢

4 个答案:

答案 0 :(得分:3)

这按3列分组;只需将%/% 3更改为%/% 5即可获得不同数量的列。 (这假设每个分组中的列数相等。)

out <- do.call(rbind, lapply(split.default(dat[,-1], (seq_along(dat[,-1])-1) %/% 3), 
                             function(a) cbind(dat[,1,drop=FALSE], unname(a))))
out
#     V1 1 2 3
# 0.1  a 1 2 3
# 0.2  b 7 8 9
# 0.3  c 4 5 6
# 1.1  a 4 5 6
# 1.2  b 1 2 3
# 1.3  c 7 8 9

我们可以用

将其清理干净
row.names(out) <- NULL
out[order(out[,1]),]
#   V1 1 2 3
# 1  a 1 2 3
# 4  a 4 5 6
# 2  b 7 8 9
# 5  b 1 2 3
# 3  c 4 5 6
# 6  c 7 8 9

答案 1 :(得分:1)

如果所显示的数据是所显示的数据,则可以通过轻松地对列进行子设置来完成,并且在将列名设置为相同后rbind将数据集设置为

library(dplyr)
rbind(df1[1:4], setNames(df1[c(1, 5:7)], names(df1)[1:4])) %>% 
      arrange(1)

如果有很多列,则更容易理解的自动方法是seq。遍历索引序列,将列rbind内的列do.call子集化,我们通过循环创建list

out <- cbind(df1[1], do.call(rbind, lapply(seq(2, ncol(df1), by = 3),
    function(i) setNames(df1[i:(i+2)], paste0("v", 2:4)))))
out[order(out$v1),]

数据

df1 <- structure(list(v1 = c("a", "b", "c"), v2 = c(1L, 7L, 4L), v3 = c(2L, 
8L, 5L), v4 = c(3L, 9L, 6L), v5 = c(4L, 1L, 7L), v6 = c(5L, 2L, 
8L), v7 = c(6L, 3L, 9L)), class = "data.frame", row.names = c(NA, 
-3L))

答案 2 :(得分:1)

这是另一个基本的R选项

cbind(
  df[rep(1:nrow(df), each = 2), ][1],
  do.call(
    "+",
    lapply(0:1,
      FUN = function(k) {
        kronecker(
          as.matrix(df[-1][(3*k-1)+2:4]),
          (matrix(c(1, 0), nrow = 2) + k) %% 2
        )
      }
    )
  )
)

这样

    V1 1 2 3
1    a 1 2 3
1.1  a 4 5 6
2    b 7 8 9
2.1  b 1 2 3
3    c 4 5 6
3.1  c 7 8 9

答案 3 :(得分:0)

使用tidyverse

硬编码版本

  1. 使用select

    隔离前4列(三个值和键)
  2. rbindselect最后三列和键

  3. 编辑请确保将要与rbind合并的列重命名为与上述步骤1中的选择df相同的名称。

  4. arrange

      df %>% 
       select(1:4) %>% 
       rbind(df %>% select(1, "v1" = 5,
                              "v2" = 6, 
                              "v3" = 7)) %>%
       arrange(key)
    
    
    
         #    key v1 v2 v3
         # 1   a  1  2  3
         # 2   a  4  5  6
         # 3   b  7  8  9
         # 4   b  1  2  3
         # 5   c  4  5  6
         # 6   c  7  8  9
    

EDIT通用(有点毛)

样本df

   set.seed(42)
    df_2 <- tibble(
      bug = letters,
      col1 = sample(1:26),
      col2 = sample(1:26),
      col3 = sample(1:26),
      col4 = sample(1:26),
      col5 = sample(1:26),
      col6 = sample(1:26),
      col7 = sample(1:26),
      col8 = sample(1:26),
      col9 = sample(1:26),
      col10 = sample(1:26),
      col11 = sample(1:26),
      col12 = sample(1:26),
      col13 = sample(1:26),
      col14 = sample(1:26),
      col15 = sample(1:26)
    )

满足通用方法的功能

   create_rowgroups.f <- function(df, key, groupsize){
  if( !(key %in% colnames(df)) ){
    print(paste(key, "is expected to be a column in df"))
    stop()
  }
  if( (ncol(df)-1) %% groupsize != 0 ){
    print("Function requires groups to fit all variable columns with the exception of the key")
    stop()
  }
  fnames = colnames(df[ , 1: (groupsize + 1) ])      
  df_2 <- bind_rows(lapply(
    1:(ncol(df)/groupsize),
    function(df, groupsize, key, fnames, index){
      pos1 = (index * groupsize) - groupsize + 2
      pos2 = (index * groupsize) + 1
      tempdf <- df %>% select(!!key, !!pos1:!!pos2)
      colnames(tempdf) = fnames
      return(tempdf)
    },
    df = df,
    key = key,
    fnames = fnames,
    groupsize = groupsize
  ))
  df_2 <- df_2 %>% arrange(across(.cols = key))
  return(df_2)
}

这是很多代码,它们围绕着lapply的简单行,以帮助OP使用UDF create_rowgroups.f