2015-06-03 1 views
1

У меня проблемы с совпадением и вставкой. У меня есть кадр данных, какСоответствие и вставка с кадрами данных в R

df 
#  X1 X2 X3 X4 X5 X6 
#t1 <NA> <NA> AU 78 <NA> <NA> 
#t2 dA AK <NA> <NA> 5 <NA> 
#t3 ip <NA> <NA> <NA> <NA> <NA> 
#t4 <NA> <NA> <NA> <NA> <NA> BA 

Я хочу, чтобы это выглядело, как это после операции,

newdf 
#  X1 X2 X3 X4 X5 X6 
#v1 <NA> <NA> <NA> <NA> <NA> <NA> 
#v2 AU78 <NA> <NA> <NA> <NA> <NA> 
#v3 AK5 <NA> <NA> <NA> <NA> <NA> 
#v4 <NA> <NA> <NA> <NA> <NA> BA 

Процесс должен первый поиск значений, которые начинаются с «A». df[1,3], df[2,2] в этом случае. Затем вставьте это значение в любые другие номера, расположенные справа от него (справа от него будет один номер). Кроме того, чтобы помочь, никогда не будет бродячих символов между целевым элементом (например, «AK») и числом справа от него; только НС разделит их.

Эти комбинированные новые значения должны быть приведены к первому столбцу, а одна строка - к той, где она была. Не имеет значения, перезаписываются ли значения, существующие в первой строке.

Мой шаблон локатор,

pat.locate <- lapply(df, function(x) grep('^A', x)) 
un.pat <- unlist(pat.locate) 
#X2 X3 
# 2 1 

Это было похоже на хороший старт. Оттуда

df[un.pat, names(un.pat)] 
#  X2 X3 
#t2 AK <NA> 
#t1 <NA> AU 

Таким образом, целевые значения найдены с их индексами столбцов и строк. Но мне нужны значения справа от этих индексов. Для подмножества целых строк,

full.row <- df[un.pat, ] 
#  X1 X2 X3 X4 X5 X6 
#t2 dA AK <NA> <NA> 5 <NA> 
#t1 <NA> <NA> AU 78 <NA> <NA> 

счетных значений не-NA, но вы можете сказать, что это произойдет,

paste(full.row[!is.na(full.row)], collapse='') 
#[1] "dAAKAU785" 

Чтобы разделить его, в apply над рядами использовали:

pasty <- function(x) paste(x[!is.na(x)], collapse='') 
pasted.rows <- apply(full.row, 1, pasty) 
#  t2  t1 
#"dAAK5" "AU78" 

Это все еще оставляет пустую строку в начале. Если я нашел хорошее регулярное выражение, чтобы сказать ему, чтобы бросить, что от меня бы,

good.regex 
# t2  t1 
# "AK5" "AU78" 

я мог тогда подмножество всего кадра данных на основе этих показателей с,

df[names(good.regex), 1] <- good.regex 
df 
#  X1 X2 X3 X4 X5 X6 
#t1 AU78 <NA> AU 78 <NA> <NA> 
#t2 AK5 AK <NA> <NA> 5 <NA> 
#t3 ip <NA> <NA> <NA> <NA> <NA> 
#t4 <NA> <NA> <NA> <NA> <NA> BA 

Но я по-прежнему осталось перемещать вставленные значения на один.

df[names(good.regex)+1, 1] <- good.regex 
#Error in names(good.regex) + 1 : non-numeric argument to binary operator 

Мы, очевидно, не можем добавить числовое подмножество под названием. Я чувствую, что на раннем этапе я пропустил какой-то элемент, что привело меня к сложному пути решения. Регулярное выражение должно быть sub, которое использует совпадение шаблона и внешний вид, который я не могу взломать. Я думаю, что я работаю в углу, который не нужен. Любая помощь приветствуется.

данных

df <- structure(list(X1 = c(NA, "dA", "ip", NA), X2 = c(NA, "AK", NA, 
NA), X3 = c("AU", NA, NA, NA), X4 = c("78", NA, NA, NA), X5 = c(NA, 
"5", NA, NA), X6 = c(NA, NA, NA, "BA")), .Names = c("X1", "X2", 
"X3", "X4", "X5", "X6"), row.names = c("t1", "t2", "t3", "t4" 
), class = "data.frame") 

newdf <- structure(list(X1 = structure(c(NA, 2L, 1L, NA), .Names = c("v1", 
"v2", "v3", "v4"), .Label = c("AK5", "AU78"), class = "factor"), 
    X2 = structure(c(NA_integer_, NA_integer_, NA_integer_, NA_integer_ 
    ), .Names = c("v1", "v2", "v3", "v4"), .Label = character(0), class = "factor"), 
    X3 = structure(c(NA_integer_, NA_integer_, NA_integer_, NA_integer_ 
    ), .Names = c("v1", "v2", "v3", "v4"), .Label = character(0), class = "factor"), 
    X4 = structure(c(NA_integer_, NA_integer_, NA_integer_, NA_integer_ 
    ), .Names = c("v1", "v2", "v3", "v4"), .Label = character(0), class = "factor"), 
    X5 = structure(c(NA_integer_, NA_integer_, NA_integer_, NA_integer_ 
    ), .Names = c("v1", "v2", "v3", "v4"), .Label = character(0), class = "factor"), 
    X6 = structure(c(NA, NA, NA, 1L), .Names = c("v1", "v2", 
    "v3", "v4"), .Label = "BA", class = "factor")), .Names = c("X1", 
"X2", "X3", "X4", "X5", "X6"), row.names = c("v1", "v2", "v3", 
"v4"), class = "data.frame") 

ответ

0

За то, что я понимаю, в соответствии с вашими выходными, например, точка, чтобы свернуть A* характер и его следующий номер в той же строке, а затем переместить этот новый объект вниз к первому столбцу один ниже. При «стирании» исходной строки (строка 1 из newdf, заполненная NA), но сохраняя линии без неповрежденного, если они не затронуты предыдущим движением (строка 4).

Ваша основная проблема должна была рухнуть на полную строку, а не сворачивать только ее конец.

## original data 
df <- structure(list(X1 = c(NA, "dA", "ip", NA), 
        X2 = c(NA, "AK", NA, NA), 
        X3 = c("AU", NA, NA, NA), 
        X4 = c("78", NA, NA, NA), 
        X5 = c(NA, "5", NA, NA), 
        X6 = c(NA, NA, NA, "BA")), 
       .Names = c("X1", "X2", "X3", "X4", "X5", "X6"), 
       row.names = c("t1", "t2", "t3", "t4"), class = "data.frame") 

df 
    X1 X2 X3 X4 X5 X6 
t1 <NA> <NA> AU 78 <NA> <NA> 
t2 dA AK <NA> <NA> 5 <NA> 
t3 ip <NA> <NA> <NA> <NA> <NA> 
t4 <NA> <NA> <NA> <NA> <NA> BA 

Это следующая функция захват строки с шаблоном согласования, но разрушиться только из этой модели до конца строки, забывая при этом своем начале. Таким образом, избегая проблемы, связанные с не сталкивались согласующим паразитным символом (dA вашего примера):

locateAndPaste <- function(x){ 
    if(TRUE %in% grepl('^A', df[x,])){ 
    endRow <- df[x, grep('^A', df[x,]):length(df)] 
    pasted.rows <- paste(endRow[!is.na(endRow)], collapse='') 
    } 
    else{NA} 
} 

else элемента предотвращает выбрасывание ошибки, если совпадение не найдено.

newEntity <- sapply(1:nrow(df), locateAndPaste) 
# [1] "AU78" "AK5" NA  NA 

Два соответствия шаблона был найден в строке 1 и 2, и ни в строке 3 и 4. Как вы можете видеть коллапсирующую часть работала отлично.

Ваша вторая проблема заключалась в перемещении одной строки вниз и невозможности добавления номера в строку символов. Поскольку я не подмножаюсь по именам, а по индексам, проблему легко избежать:

(для того, чтобы быть полным, я добавил строку в конце этого сообщения относительно преобразования в числовое число эти имена)

## the newEntity element is already ordered according to the original row numbers 
originalRowNumbers <- grep("^A", newEntity) 
# [1] 1 2 

с тех пор, это довольно прямо вперед:

newdf <- df ## all operations can be done on the original df, 
       ## this copy is made only for the sake of the example. 

## as per your example, "erase" the original lines where a matching pattern was found 
## that will also prevent orphan lines if a no match have been found in the above line 
newdf[originalRowNumbers, ] <- rep(NA, length(df)) 

## place the new entity in the first column one row below 
newdf[originalRowNumbers+1, 1] <- newEntity[originalRowNumbers] 
## fill the rest of this row with NA as per your example 
newdf[originalRowNumbers+1, 2:length(df)] <- NA 


newdf 
    X1 X2 X3 X4 X5 X6 
t1 <NA> <NA> <NA> <NA> <NA> <NA> 
t2 AU78 <NA> <NA> <NA> <NA> <NA> 
t3 AK5 <NA> <NA> <NA> <NA> <NA> 
t4 <NA> <NA> <NA> <NA> <NA> BA 

Однако, если шаблон согласования должны были быть найдены в последней строке, дополнительная строка будет добавлена ​​в newdf. Для того, чтобы избежать этого, можно сократить первоначальный выбор:

newEntity <- sapply(1:(nrow(df)-1), locateAndPaste) 


быть полным: в вашем примере, что можно захватить только номер в названиях good.regex, а затем кормить их ваше подмножество:

idx.goood.regex <- as.numeric(gsub("t","", names(good.regex))) 
# [1] 2 1 
df[idx.good.regex+1, 1] <- good.regex 

Обратите внимание, что работает только потому, что good.regex имеет классовый характер. Произошла ошибка, если good.regex - это data.frame.