Разделение столбца строки dataframe на несколько разных столбцов
то, что я пытаюсь сделать, это разделить столбец на несколько столбцов. Я бы предпочел, чтобы первый столбец содержал "F", второй столбец "US", третий "CA6" или "DL", а четвертый - "Z13" или "U13" и т. д. Весь мой df следует той же схеме X. XX.XXXX.XXX или X. XX.XXX.XXX или X. XX.XX.XXX и я знаю, что третья колонка-это моя проблема из-за разной длины. Я только использовал substr в прошлом, и я мог бы использовать это здесь с некоторыми утверждениями if, но хотел бы чтобы узнать, как использовать пакет stringr и POSIX для этого (если нет лучшего варианта). Заранее спасибо.
вот мой df:
c("F.US.CLE.V13", "F.US.CA6.U13", "F.US.CA6.U13", "F.US.CA6.U13",
"F.US.CA6.U13", "F.US.CA6.U13", "F.US.CA6.U13", "F.US.CA6.U13",
"F.US.DL.U13", "F.US.DL.U13", "F.US.DL.U13", "F.US.DL.Z13", "F.US.DL.Z13"
)
3 ответов
очень прямой способ-просто использовать read.table
на вектор символов:
> read.table(text = text, sep = ".", colClasses = "character")
V1 V2 V3 V4
1 F US CLE V13
2 F US CA6 U13
3 F US CA6 U13
4 F US CA6 U13
5 F US CA6 U13
6 F US CA6 U13
7 F US CA6 U13
8 F US CA6 U13
9 F US DL U13
10 F US DL U13
11 F US DL U13
12 F US DL Z13
13 F US DL Z13
colClasses
необходимо указать, в противном случае F
преобразуется к виду FALSE
(что мне нужно исправить в "splitstackshape", иначе я бы рекомендовал это :))
обновление (>год спустя)...
кроме того, вы можете использовать мой cSplit
функции, например:
cSplit(as.data.table(text), "text", ".")
# text_1 text_2 text_3 text_4
# 1: F US CLE V13
# 2: F US CA6 U13
# 3: F US CA6 U13
# 4: F US CA6 U13
# 5: F US CA6 U13
# 6: F US CA6 U13
# 7: F US CA6 U13
# 8: F US CA6 U13
# 9: F US DL U13
# 10: F US DL U13
# 11: F US DL U13
# 12: F US DL Z13
# 13: F US DL Z13
или separate
из "tidyr", как это:
library(dplyr)
library(tidyr)
as.data.frame(text) %>% separate(text, into = paste("V", 1:4, sep = "_"))
# V_1 V_2 V_3 V_4
# 1 F US CLE V13
# 2 F US CA6 U13
# 3 F US CA6 U13
# 4 F US CA6 U13
# 5 F US CA6 U13
# 6 F US CA6 U13
# 7 F US CA6 U13
# 8 F US CA6 U13
# 9 F US DL U13
# 10 F US DL U13
# 11 F US DL U13
# 12 F US DL Z13
# 13 F US DL Z13
это то, что вы пытаетесь сделать?
# Our data
text <- c("F.US.CLE.V13", "F.US.CA6.U13", "F.US.CA6.U13", "F.US.CA6.U13",
"F.US.CA6.U13", "F.US.CA6.U13", "F.US.CA6.U13", "F.US.CA6.U13",
"F.US.DL.U13", "F.US.DL.U13", "F.US.DL.U13", "F.US.DL.Z13", "F.US.DL.Z13"
)
# Split into individual elements by the '.' character
# Remember to escape it, because '.' by itself matches any single character
elems <- unlist( strsplit( text , "\." ) )
# We know the dataframe should have 4 columns, so make a matrix
m <- matrix( elems , ncol = 4 , byrow = TRUE )
# Coerce to data.frame - head() is just to illustrate the top portion
head( as.data.frame( m ) )
# V1 V2 V3 V4
#1 F US CLE V13
#2 F US CA6 U13
#3 F US CA6 U13
#4 F US CA6 U13
#5 F US CA6 U13
#6 F US CA6 U13
С помощью unlist
и matrix
кажется немного запутанным и требует от вас жесткого кода количества элементов (на самом деле это довольно большой запрет. Конечно, вы можете обойти жесткое кодирование этого числа и определить его во время выполнения)
Я бы пошел по другому пути, и создать фрейм данных непосредственно из списка, что strsplit
возвращает. Для меня это концептуально проще. Существует два способа сделать это:
-
as.data.frame
- но так как список является совершенно неправильным (у нас есть список строк, а не список столбцов), мы должны транспонировать результат. Мы также очищаемrownames
так как они уродливы по умолчанию (но это совершенно необязательно!):`rownames<-`(t(as.data.frame(strsplit(text, '\.'))), NULL)
-
можно использовать
rbind
для построения фрейма данных из списка строк. Мы используемdo.call
называтьrbind
со всеми строками в качестве отдельных аргументов:do.call(rbind, strsplit(text, '\.'))
оба выхода путей тот же результат:
[,1] [,2] [,3] [,4]
[1,] "F" "US" "CLE" "V13"
[2,] "F" "US" "CA6" "U13"
[3,] "F" "US" "CA6" "U13"
[4,] "F" "US" "CA6" "U13"
[5,] "F" "US" "CA6" "U13"
[6,] "F" "US" "CA6" "U13"
…
очевидно, что второй способ намного проще, чем первый.