2015-12-17 3 views
1

У меня есть кадр данныхразделить столбец строки в нескольких столбцах

df=data.frame(x=rnorm(8),y=runif(8),longstring=c("foo_100_Case1","foo_125_Case1","bar_100_Case1","bar_125_Case1","foo_100_Case2","foo_125_Case2","bar_100_Case2","bar_125_Case2"),stringsAsFactors = F) 

Мне нужно разделить последнюю колонку в трех колонках, с разделителем «_». Я делал следующее:

a=matrix(unlist(strsplit(df$longstring,"_",fixed=T)),8,3,byrow = T) 
df$type=a[,1] 
df$point=a[,2] 
df$case=a[,3] 

Но мне интересно, если есть более простой способ: сочетание strsplit и unlist особенно неудобно, и это не делает код очень читаемым.

+1

Функция 'separate' в пакете ** ** tidyr был специально написан для этого. – joran

ответ

4

Вы можете попробовать,

cbind(df[-3], data.frame(do.call('rbind', strsplit(df$longstring,'_')))) 

# x    y X1 X2 X3 
#1 -0.5522704 0.9998266 foo 100 Case1 
#2 1.1907351 0.8979460 foo 125 Case1 
#3 0.6005691 0.4301610 bar 100 Case1 
#4 -1.0698081 0.9626781 bar 125 Case1 
#5 -0.8526932 0.9634738 foo 100 Case2 
#6 0.0100209 0.2968137 foo 125 Case2 
#7 -1.5051358 0.7012956 bar 100 Case2 
#8 1.0892584 0.4655736 bar 125 Case2 

do.call функция позволяет вызвать любую функцию R и вместо того, чтобы послать аргумент один за другим вы можете использовать список для хранения аргументов. Больше информации ?do.call. do.call возвращает только X1, X2 ии для получения исходного фрейма данных я использую cbind для связывания исходных столбцов. strsplit, как вы уже знаете, разбивает строку на _.


Или, как @joran упоминалось вы можете использовать separate из tidyr пакета как

library(tidyr) 
separate(df, longstring, c("X1", "X2", "X3"), sep="_") 

# x    y X1 X2 X3 
#1 -0.5522704 0.9998266 foo 100 Case1 
#2 1.1907351 0.8979460 foo 125 Case1 
#3 0.6005691 0.4301610 bar 100 Case1 
#4 -1.0698081 0.9626781 bar 125 Case1 
#5 -0.8526932 0.9634738 foo 100 Case2 
#6 0.0100209 0.2968137 foo 125 Case2 
#7 -1.5051358 0.7012956 bar 100 Case2 
#8 1.0892584 0.4655736 bar 125 Case2 
+0

Определенно более читаемый, чем мой, и мне нравится, что вы отбрасываете 'df $ longstring'. Не могли бы вы объяснить свой код? Что такое 'do.call'? Зачем вам нужны «cbind» и «rbind»? Почему в вашем коде вам нужен 'as.character', в то время как в моем я могу напрямую писать' strsplit (df $ longstring ...) '? – DeltaIV

+1

Хорошо, мне больше нравится синтаксис 'tidyr'. Обычно мне не нравится устанавливать пакеты для работы, которые могут быть сделаны в базе R, но мне очень нравится, что 'tidyr' позволяет мне разделить и переименовать столбцы за один раз. И синтаксис гораздо читабельнее! – DeltaIV

+0

@DeltaIV вы правы, 'tidyr' более читабельна, и также нет необходимости в' as.character' в 'strsplit', следовательно, обновляется –

6

Вот еще несколько вариантов, чтобы попробовать:

Мой пакет "splitstackshape" предназначен для этого виды товаров ...

library(splitstackshape) 
cSplit(df, "longstring", "_") 
#    x   y longstring_1 longstring_2 longstring_3 
# 1: -1.41524742 0.2123978   foo   100  Case1 
# 2: -1.09240237 0.3899935   foo   125  Case1 
# 3: 0.39675025 0.2162463   bar   100  Case1 
# 4: -1.14996728 0.7608128   bar   125  Case1 
# 5: -0.07657172 0.6878348   foo   100  Case2 
# 6: 0.29549599 0.2216566   foo   125  Case2 
# 7: 1.78622612 0.1496666   bar   100  Case2 
# 8: -0.11749579 0.9255409   bar   125  Case2 

«data.table» пакет приносит нам быстрые tstrsplit функцию ...

library(data.table) 
as.data.table(df)[ 
    , paste0("V", 1:3) := tstrsplit(longstring, "_")][ 
    , longstring := NULL][] 

Если у вас есть время и хотите ждать read.table делать свою работу ...

cbind(df[1:2], read.table(text = df$longstring, sep = "_")) 

Если йо и нужно еще что-то быстро ...

library(iotools) 
cbind(df[1:2], mstrsplit(df$longstring, sep = "_"))