как подобрать набор чисел с конца строк неправильной длины в R? - PullRequest
1 голос
/ 31 августа 2010

Мне нужно взять несколько чисел из строк неправильной длины, например:

AAAAAAAAA 250.00
BBB 240.00
CCCCCCC 13.00

Мне нужно захватить 250,00, 240,00 и 13,00, но так как числовые и символьные строки нерегулярны, я не могу использовать для этого «substr», я думаю, что регулярное выражение может быть решением, но я не знаю об этом. 1004 *

Кто-нибудь может помочь? Спасибо!

РЕДАКТИРОВАТЬ # 1

Спасибо за быстрый ответ Джошуа, но я боюсь, что это не совсем так, поскольку пробелы и цифры могут также присутствовать в строках AAAAAAAA, BBB, CCCCC.

Еще раз спасибо.

РЕДАКТИРОВАТЬ # 2

Джошуа, я пытался, но все равно не получилось, я покажу пример строки здесь:

 01 JUN 2003 02 JUN 2002 OCTOPUS CARDS LTD HONG KONG HK 250.00

Надеюсь, это поможет, и еще раз спасибо.

РЕДАКТИРОВАТЬ # 3

Джошуа, еще раз спасибо.

Теперь у меня есть более сложный случай:

 01 JUN 2003 02 JUN 2002 OCTOPUS CARDS LTD HONG KONG HK 834591283405347 250.00

"OCTOPUS CARDS LTD HONG KONG HK" И "834591283405347" - это две отдельные колонки, и я хочу также извлечь их, как я могу это сделать?

Ответы [ 6 ]

2 голосов
/ 31 августа 2010

К сожалению, хвост относительно медленный. На самом деле индексирование последнего элемента выполняется намного быстрее.

FUN <- function(x) {ss <- strsplit(x,' ')[[1]];ss[length(ss)]}

На моей машине это вдвое быстрее, чем команда tail.

y <- c("AAAAAAAAAAA 250.00",
    "01 JUN 2003 02 JUN 2002 OCTOPUS CARDS LTD HONG KONG HK 5.13",
    "01 JUN 2003 02 JUN 2002 OCTOPUS CARDS LTD HONG KONG HK 834591283405347 50.00")    

#make y bigger so that there's something to test
y <- rep(y, 1e5)

#testing tail
FUN <- function(x) {tail(strsplit(x,' ')[[1]],1)}
system.time( lapply(y,FUN) )       
   user  system elapsed 
 22.108   0.110  22.069 

#testing indexing
FUN <- function(x) {ss <- strsplit(x,' ')[[1]];ss[length(ss)]}    
system.time( lapply(y,FUN) )
  user  system elapsed 
 9.396   0.037   9.372 

Но еще большая скорость достигается за счет разделения функции и использования факта, что компоненты уже векторизованы. (Весь смысл применения семейства команд состоит не в том, чтобы заменить циклы, а в том, чтобы разрешить простой синтаксис и максимально использовать векторизованные команды. Простейшие функции, которые должны быть выполнены, должны быть в порядке и тому подобное.)

#first let strsplit do it's own vectory magic
s <- strsplit(y, ' ')
#then define a simpler function
FUN <- function(x) x[length(x)]
lapply(s, FUN)

Чтобы проверить время, необходимо сохранить strsplit внутри процедуры синхронизации, чтобы сделать ее справедливой

system.time( {s <- strsplit(y, ' ');lapply(s, FUN)} )

   user  system elapsed 
  5.281   0.048   5.305 

(Я почти уверен, что что-то упустил в индексировании списков, и моя функция должна быть еще проще.)

Еще одна вещь, хотя ... и это ускорило бы весь процесс, но я просто добавлю это здесь. strsplit () имеет фиксированную опцию. Это работает намного быстрее, если вы установите значение true, если вы не используете регулярное выражение.

system.time( {s <- strsplit(y, ' ', fixed = TRUE); lapply(s, FUN)} )
   user  system elapsed 
  1.256   0.007   1.253 

Если вы делаете это для большого набора данных или вам приходится часто делать это даже для наборов данных среднего размера, вам действительно следует использовать этот последний метод. Это почти в 20 раз быстрее.

Вот окончательное решение, которое можно просто скопировать для выполнения всей задачи, предполагая, что Y - это вектор символьных строк, отформатированный так, как ожидалось в Edit # 3. Ожидается, что последний элемент представляет собой денежную ценность для сохранения, а второй последний элемент является своего рода идентификатором.

s <- strsplit(y, ' ', fixed = TRUE)
moneyVal <- lapply(s, function(x) x[length(x)])
   idVal <- lapply(s, function(x) x[length(x)-1])
 restOfY <- lapply(s, function(x) paste(x[1:(length(x)-2)], collapse = ' '))
#These three values can be combined into a data frame
df <- data.frame(restOfY, idVal, moneyVal)
2 голосов
/ 31 августа 2010

Если у вас есть только два столбца в каждой из ваших строк данных, вы можете использовать read.table() с textConnection():

x = "AAAAAAAAA 250.00
BBB 240.00
CCCCCCC 13.00"

data = read.table(textConnection(x))

data

             V1  V2
    1 AAAAAAAAA 250
    2       BBB 240
    3   CCCCCCC  13

и

data[2]
   V2
1 250
2 240
3  13
1 голос
/ 31 августа 2010

Если ваша реальная проблема похожа на ваш пример:

> lapply(c("AAAAAAA 250.00","BBB 240.00"), function(x) strsplit(x, " ")[[1]][2]) 
[[1]]
[1] "250.00"

[[2]]
[1] "240.00"

РЕДАКТИРОВАТЬ 1: Поскольку ваша реальная проблема не точно как ваш пример:; -)

> y <- c("AAAAAAAAAAA 250.00","BBBBB 240.00","CC CC 120.00")
> FUN <- function(x) substr(x,regexpr("[0-9]",x),nchar(x))
> lapply(y,FUN)
[[1]]
[1] "250.00"

[[2]]
[1] "240.00"

[[3]]
[1] "120.00"

РЕДАКТИРОВАТЬ 2: Изменить FUN на:

> FUN <- function(x) tail(strsplit(x," ")[[1]],1)
0 голосов
/ 31 августа 2010

Вы должны взглянуть на пакет gsubfn, особенно на функцию strapply.

Функция strapply фокусируется на том, что вы хотите найти (а не на том, что вы хотите разделить, или на том, что вы хотите удалить).

Простой случай - просто дать ему шаблонсопоставьте число, и вы получите все числа из строки, или вы можете включить '$', чтобы получить только цифры в конце строки, или изменить шаблон так, чтобы он точно соответствовал вашим ожиданиям.

0 голосов
/ 31 августа 2010

Использование gsub:

y <- c(
    "AAAAAAAAAAA 250.00",
    "BBBBB 240.00",
    "CC CC 120.00",
    "01 JUN 2003 02 JUN 2002 OCTOPUS CARDS LTD HONG KONG HK 250.00",
    "01 JUN 2003 02 JUN 2002 OCTOPUS CARDS LTD HONG KONG HK 834591283405347 250.00"
)

gsub("(^.* )([0-9\\.]*$)", "\\2", y)
# [1] "250.00" "240.00" "120.00" "250.00" "250.00"

или

gsub("^.* ", "", y)
# [1] "250.00" "240.00" "120.00" "250.00" "250.00"

Проверьте также эту тему о работе с подстроками .

0 голосов
/ 31 августа 2010

Я бы хотел немного больше информации, чтобы быть уверенным. Но всегда ли это «произвольный текст [пробел] число»?

Если это так, вы могли бы сделать что-то вроде

> read.csv("~/Desktop/test.txt", sep=" ", header=FALSE)
         V1  V2
1 AAAAAAAAA 250
2       BBB 240
3   CCCCCCC  13

Предполагается, что вы сохранили текст в файл (~ / Desktop / test.txt). Числовые строки автоматически приводятся к числам.

> sum(a$V2)
[1] 503
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...