2016-06-09 1 views
2

Учитывая dataframe df:Split или отдельные неровные/неравные строки без каких-либо разделителей

x <- c("X1", "X2", "X3", "X4", "X5") 
y <- c("00L0", "0", "00012L", "0123L0", "0D0") 
df <- data.frame(x, y) 

Как я могу использовать tidyr::separate поставить каждый символ y строки в отдельный столбец (один столбец на строки позиции)?

Желаемый выход:

x <- c("X1", "X2", "X3", "X4", "X5") 
m1 <- c(0, 0, 0, 0, 0) 
m2 <- c(0, NA, 0, 1, "D") 
m3 <- c("L", NA, 0, 2, 0) 
mN <- c(NA, NA, NA, NA, NA) 
df <- data.frame(x, m1, m2, m3, mN) 

Где мН теоретически может доходить до m100 (100 столбцов) или выше.

ответ

6

Это работает. Он заполняется пробелами, а не NA, но вы можете изменить этот пост-hoc, если хотите. (fill = 'right' работает только при разбиении на вектор символов, а не явные позиции.)

maxchar = max(nchar(as.character(df$y))) 
tidyr::separate(df, y, into = paste0("y", 1:maxchar), sep = 1:(maxchar - 1)) 

# x y1 y2 y3 y4 y5 y6 
# 1 X1 0 0 L 0   
# 2 X2 0     
# 3 X3 0 0 0 1 2 L 
# 4 X4 0 1 2 3 L 0 
# 5 X5 0 D 0  
4

Вот базовый метод R.

# split the strings 
temp <- strsplit(df$y, split="") 
# maximum length of the list items 
maxL <- max(sapply(temp, length)) 
# contstruct data.frame with NAs as fills 
temp <- data.frame(do.call(rbind, lapply(temp, function(i) c(i, rep(NA, maxL-length(i)))))) 

# add to df 
df <- cbind(x=df[, -2], temp) 

что приводит к

 x X1 X2 X3 X4 X5 X6 
1  X1 0 0 L 0 <NA> <NA> 
2  X2 0 <NA> <NA> <NA> <NA> <NA> 
3  X3 0 0 0 1 2 L 
4  X4 0 1 2 3 L 0 
5  X5 0 D 0 <NA> <NA> <NA> 

Я использовал stringsAFactors = FALSE в создании ДФ:

df <- data.frame(x, y, stringsAsFactors = F) 

Но, если бы я не сделал, этот код приведет к ошибка как @ m0h3n указывает. Без этой альтернативной конструкции data.frame, необходимо обернуть ф.р. $ у в as.character принуждать переменной от фактора к персонажу:

# split the strings 
temp <- strsplit(as.character(df$y), split="") 

Спасибо @ m0h3n за указание на это.

+1

'as.character (df $ y)' должен быть указан для функции 'strsplit', в противном случае fa илы. – 989

+0

@ m0h3n Вы правы, учитывая приведенные выше данные. Я использовал строкиAsFactors = FALSE в функции 'data.frame', но я не упоминал об этом. Спасибо за напоминание. – lmo

+0

вполне приветствуется :) – 989

1

Вы можете разбить строку в колонке у на отдельные символы, с помощью strsplit:

> strsplit("00L0",c()) 
[[1]] 
[1] "0" "0" "L" "0" 

Начиная с кадром данных:

> df 
    x  y 
1 X1 00L0 
2 X2  0 
3 X3 00012L 
4 X4 0123L0 
5 X5 0D0 

Я решил проблему ввода этих символов в столбцы с помощью:

Первый: использовать ddply для разделения всех строк в столбце y и поместить их в отдельные строки

> ddply(df, .(x), summarise, v = 1:nchar(as.character(y)), 
     y = unlist(strsplit(as.character(y),c()))) 
    x v y 
1 X1 1 0 
2 X1 2 0 
3 X1 3 L 
4 X1 4 0 
5 X2 1 0 
6 X3 1 0 
7 X3 2 0 
8 X3 3 0 
9 X3 4 1 
10 X3 5 2 
11 X3 6 L 
12 X4 1 0 
13 X4 2 1 
14 X4 3 2 
15 X4 4 3 
16 X4 5 L 
17 X4 6 0 
18 X5 1 0 
19 X5 2 D 
20 X5 3 0 

Второе: Использование перекроить для преобразования строк с одинаковым значением х в столбцы

> reshape(ans, idvar=c("x"), timevar="v", direction="wide") 
    x y.1 y.2 y.3 y.4 y.5 y.6 
1 X1 0 0 L 0 <NA> <NA> 
5 X2 0 <NA> <NA> <NA> <NA> <NA> 
6 X3 0 0 0 1 2 L 
12 X4 0 1 2 3 L 0 
18 X5 0 D 0 <NA> <NA> <NA> 

Это может быть чрезмерно усложнять проблему, но это единственный способ, которым я мог заставить его работать!

+0

Умный подход! – Gregor

0

Вот еще base R вариант, где мы создаем разделитель , между символами столбца «у» с помощью gsub, а затем прочитать его с read.csv

cbind(df[1],read.csv(text=gsub("(?<=.)(?=.)", ",", df$y, perl=TRUE), 
       header=FALSE,fill=TRUE, na.strings = "")) 
# x V1 V2 V3 V4 V5 V6 
#1 X1 0 0 L 0 <NA> <NA> 
#2 X2 0 <NA> <NA> NA <NA> <NA> 
#3 X3 0 0 0 1 2 L 
#4 X4 0 1 2 3 L 0 
#5 X5 0 D 0 NA <NA> <NA> 

Или использовать tstrsplit из data.table

mxr = max(nchar(as.character(df$y))) 
setDT(df)[, paste0("y", seq(mxr)) := tstrsplit(y, "")]