2017-05-09 126 views
2

我有导入时看起来像这样的数据;将数据转换为R

ID col1 col2 col3 col4 
1 a e i r 
      j s 
      k t 
2 b f l u 
      m v 
      n w 
      o x 
3 c g p y 
4 d h q z 

和想它转化使得有每行一个唯一的ID,IE:

ID col1 col2 col3 col4 col5 col6 col7 col8 col9 col10 
1 a e i r j s k t 
2 b f l u m v n w o x 
3 c g p y 
4 d h q z 

在易消化的形式的数据:

df <- data.frame(ID = c(1, NA, NA, 2, NA, NA, NA, 3, 4), 
       col1 = c('a', NA, NA, 'b', NA, NA, NA, 'c', 'd'), 
       col2 = c('e', NA, NA, 'f', NA, NA, NA, 'g', 'h'), 
       col3 = letters[9:17], 
       col4 = letters[18:26]) 
+2

您可以提供数据的dput?我不确定第3列和第4列的值如何。 –

回答

0

tidyverse溶液:

df %>% 
    mutate(ID = zoo::na.locf(ID)) %>% 
    mutate(row = row_number()) %>% 
    tidyr::gather(col, val, col1:col4) %>% 
    filter(!is.na(val)) %>% 
    arrange(ID, row, col) %>% 
    select(-row) %>% 
    group_by(ID) %>% 
    mutate(col = row_number()) %>% 
    mutate(col = paste0('col', stringr::str_pad(col, side = 'left', pad = '0', width = 2))) %>% 
    tidyr::spread(col, val) 
0

下面是使用,并与一些碱沿tidyrdplyr的组合的溶液:

library(dplyr) 
library(tidyr) 

df <- fill(df, ID, .direction = 'down') 
numCols <- max(sapply(split(df, df$ID), function(x) sum(!is.na(x[, -1])))) 

df %>% 
    group_by(ID) %>% 
    do(summarise(., l = paste(unlist(.[, -1])[!is.na(unlist(.[, -1]))], collapse = ' '))) %>% 
    separate(l, into = paste0('col', 1:numCols), sep = ' ') 

输出如下:

 ID col1 col2 col3 col4 col5 col6 col7 col8 col9 col10 
* <dbl> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> 
1  1  a  e  i  j  k  r  s  t <NA> <NA> 
2  2  b  f  l  m  n  o  u  v  w  x 
3  3  c  g  p  y <NA> <NA> <NA> <NA> <NA> <NA> 
4  4  d  h  q  z <NA> <NA> <NA> <NA> <NA> <NA> 
3

需要提醒的是长形式几乎总是像箱子更加有用对此,两个备选方案:

library(tidyverse) 

df <- data.frame(ID = c(1, NA, NA, 2, NA, NA, NA, 3, 4), 
       col1 = c('a', NA, NA, 'b', NA, NA, NA, 'c', 'd'), 
       col2 = c('e', NA, NA, 'f', NA, NA, NA, 'g', 'h'), 
       col3 = letters[9:17], 
       col4 = letters[18:26]) 

df %>% fill(ID) %>% 
    gather(var, val, -ID) %>% 
    drop_na(val) %>% 
    group_by(ID) %>% 
    mutate(var = sprintf('col%02d', row_number())) %>% 
    spread(var, val) 

#> # A tibble: 4 × 11 
#> # Groups: ID [4] 
#>  ID col01 col02 col03 col04 col05 col06 col07 col08 col09 col10 
#> * <dbl> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> 
#> 1  1  a  e  i  j  k  r  s  t <NA> <NA> 
#> 2  2  b  f  l  m  n  o  u  v  w  x 
#> 3  3  c  g  p  y <NA> <NA> <NA> <NA> <NA> <NA> 
#> 4  4  d  h  q  z <NA> <NA> <NA> <NA> <NA> <NA> 

或折叠的一切ST戒指和独立:

df %>% mutate_at(vars(-ID), as.character) %>% 
    fill(ID) %>% 
    group_by(ID) %>% 
    summarise(lets = toString(na.omit(c(col1, col2, col3, col4)))) %>% 
    separate(lets, sprintf('col%02d', 1:10), fill = 'right') 

#> # A tibble: 4 × 11 
#>  ID col01 col02 col03 col04 col05 col06 col07 col08 col09 col10 
#> * <dbl> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> 
#> 1  1  a  e  i  j  k  r  s  t <NA> <NA> 
#> 2  2  b  f  l  m  n  o  u  v  w  x 
#> 3  3  c  g  p  y <NA> <NA> <NA> <NA> <NA> <NA> 
#> 4  4  d  h  q  z <NA> <NA> <NA> <NA> <NA> <NA> 
+0

非常好。比我的解决方案更清晰。我更喜欢第一个版本,因为它与列数无关(类似于我的目标)。 – Gopala

+0

顺便说一句 - 你的第二个解决方案是硬编码10,这在'更全面的数据'中可能并非如此。正如我所做的那样,计算更好。另一个原因,我喜欢第一个。 – Gopala

+0

是的,你可以在'summarise'步骤中计算长度,但是如果你对输入列进行了硬编码,这并不值得。另一个拙劣的解决方法就是让更多的列超出你的需求,然后删除完全“NA”的任何东西。 – alistaire

0

基础R不是半坏的时候:

tmp <- na.omit(data.frame(id=cummax(replace(df$ID, is.na(df$ID), 0)), col=unlist(df[-1]))) 
reshape(transform(tmp, time=ave(id,id,FUN=seq_along)), direction="wide", idvar="id", sep="") 

#  id col1 col2 col3 col4 col5 col6 col7 col8 col9 col10 
#col11 1 a e i j k r s t <NA> <NA> 
#col14 2 b f l m n o u v w  x 
#col18 3 c g p y <NA> <NA> <NA> <NA> <NA> <NA> 
#col19 4 d h q z <NA> <NA> <NA> <NA> <NA> <NA>