2017-05-09 177 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>