2014-11-17 145 views
1

我想在每個列中將由逗號分隔的值對分隔成新數據框中的兩個相鄰列,並且每個列的名稱都相同兩個新的專欄。將列拆分爲兩個具有相同列名的新列

也就是說,我想轉換此:

A B C D E 
1,1 0,1 1,1 1,1 1,1 
1,1 1,1 1,1 1,1 1,1 
0,1 0,1 0,1 0,1 0,1 

這樣:

A A B B C C D D E E 
1 1 0 1 1 1 1 1 1 1 
1 1 1 1 1 1 1 1 1 1 
0 1 0 1 0 1 0 1 0 1 

如果數據幀的名稱不能完全相同,A_1和A_2 ...等上應該沒問題。或者,將數據框的第一行中的名稱而不是標題也可以。

我的實際數據集大約200列〜13,000行,所以我需要一個自動方法來分割列併爲第二版數據框分配名稱。

回答

7

你可以使用

library(splitstackshape) 
(newdf <- cSplit(df, names(df), ",")) 
# A_1 A_2 B_1 B_2 C_1 C_2 D_1 D_2 E_1 E_2 
# 1: 1 1 0 1 1 1 1 1 1 1 
# 2: 1 1 1 1 1 1 1 1 1 1 
# 3: 0 1 0 1 0 1 0 1 0 1 

要創建重複的列名,那麼你可以做,因爲data.table下面還裝載了splitstackshape

setnames(newdf, names(newdf), sub("_.*", "", names(newdf))) 
newdf 
# A A B B C C D D E E 
# 1: 1 1 0 1 1 1 1 1 1 1 
# 2: 1 1 1 1 1 1 1 1 1 1 
# 3: 0 1 0 1 0 1 0 1 0 1 

但只是讓你知道,有重複的列名是一個可怕的想法。

+0

當然是+1,但是爲什麼在'data.table'中有'setnames'時使用'setNames'就可以不用複製呢? – A5C1D2H2I1M1N2O1R2T1

+0

是cSplit!毆打一拳。 +1 – jazzurro

+0

也可能是'cSplit_f'的更好選擇。 – A5C1D2H2I1M1N2O1R2T1

4

不要在這裏踢我自己,但隨着「stringi」包的最近發展,cSplit不再爲這種類型的工作蛋糕。

下面是使用Stringi的一種方法(雖然它特定於這個問題)。

首先,建立一個分流的功能:通過200列

Stringi(df) 
#  A1 A2 B1 B2 C1 C2 D1 D2 E1 E2 
# [1,] 1 1 0 1 1 1 1 1 1 1 
# [2,] 1 1 1 1 1 1 1 1 1 1 
# [3,] 0 1 0 1 0 1 0 1 0 1 

在13000行,cSplit需要不到11秒了我,:

library(stringi) 
Stringi <- function(indf) { 
    X <- do.call(cbind, lapply(indf, stri_split_fixed, ",", simplify = TRUE)) 
    `dimnames<-`(`dim<-`(as.numeric(X), dim(X)), 
       list(NULL, paste0(rep(names(indf), each = 2), 1:2))) 
} 

其次,應用它Stringi需要不到2.5秒。


很顯然,這是後話已經在考慮「splitstackshape」的未來版本爲this Gist of mine from last month shows :-)隨着該版本的cSplit,當時來自11秒下調至2.7秒。

+0

'stringi'現在也有'stri_list2matrix'這真的很不錯 –

+0

@RichardScriven,不適合這個。這就是'stri_split_fixed'中'simplify'參數的調用。 – A5C1D2H2I1M1N2O1R2T1

+0

@AnandaMahto非常感謝你的工作!現在我有更多要學習。 +1 :) – jazzurro