Разделить строковый вектор на пробел

У меня есть следующий вектор:

tmp3 <- c("1500 2", "1500 1", "1510 2", "1510 1", "1520 2", "1520 1", "1530 2", 
"1530 1", "1540 2", "1540 1")

Я хотел бы просто сохранить второе число в каждом из атомов этого вектора, чтобы оно читалось:

c(2,1,2,1,2,1,2,1,2,1)

person Zak    schedule 04.11.2009    source источник
comment
Не могли бы вы принять ответ, чтобы отметить вопрос как решенный?   -  person MERose    schedule 29.12.2015


Ответы (9)


Вероятно, есть лучший способ, но вот два подхода с strsplit():

as.numeric(data.frame(strsplit(tmp3, " "))[2,])
as.numeric(lapply(strsplit(tmp3," "), function(x) x[2]))

as.numeric() может не понадобиться, если вы можете использовать символы...

person Shane    schedule 04.11.2009
comment
Это элегантное решение. Как раз то, что я искал. Спасибо! - person Zak; 05.11.2009
comment
Я пытался использовать ваше решение, но вместо этого использовал столбец фрейма данных, и это не сработало сразу. Я бы добавил, что для этих случаев вам нужно превратить его в список. as.numeric(data.frame(strsplit(as.list(df$columnx), " "))[2,]) - person pedrosaurio; 02.05.2013

Можно было бы использовать read.table на textConnection:

X <- read.table(textConnection(tmp3))

потом

> str(X)
'data.frame':   10 obs. of  2 variables:
 $ V1: int  1500 1500 1510 1510 1520 1520 1530 1530 1540 1540
 $ V2: int  2 1 2 1 2 1 2 1 2 1

так что X$V2 это то, что вам нужно.

person Marek    schedule 05.11.2009

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

gsub(".+\\s+", "", tmp3)
[1] "2" "1" "2" "1" "2" "1" "2" "1" "2" "1"

Если вы пытаетесь реализовать более сложное правило, чем «брать все после пробела», вам понадобится более сложное регулярное выражение.

person SchaunW    schedule 30.04.2013
comment
можешь объяснить это… - person user3067923; 17.11.2016
comment
функция gsub предназначена для замены совпадений регулярных выражений чем-то другим. В этом случае мы используем регулярное выражение .+\\s+ и заменяем все найденные совпадения пустой строкой "". Регулярное выражение преобразуется в «Сопоставить что угодно» в начале, но оно должно заканчиваться пробелом (пробел записывается как \\s) - person Corey Levinson; 18.09.2017

Я думаю, что это самый элегантный способ сделать это

>     res <- sapply(strsplit(tmp3, " "), "[[", 2)

Если вам нужно, чтобы это было целое число

>     storage.mode(res) <- "integer"
person ephpostfacto    schedule 06.11.2009
comment
Кроме того, res <- as.numeric(sapply(...)) тоже работает; storage.mode немного страшно - person user295691; 01.05.2013

substr(x = tmp3, start = 6, stop = 6)

Пока ваши строки всегда одинаковой длины, это должно сработать.

(И, конечно же, вам не нужно указывать имена аргументов — substr(tmp3, 6, 6) тоже отлично работает)

person Matt Parker    schedule 04.11.2009

Это должно сделать это:

library(plyr)
ldply(strsplit(tmp3, split = " "))[[2]]

Если вам нужен числовой вектор, используйте

as.numeric(ldply(strsplit(tmp3, split = " "))[[2]])
person Paolo    schedule 06.11.2009

Другой вариант — scan(). Чтобы получить второе значение, мы можем использовать логическое подмножество.

scan(text = tmp3)[c(FALSE, TRUE)]
#  [1] 2 1 2 1 2 1 2 1 2 1
person Rich Scriven    schedule 29.07.2015

Просто добавить еще два варианта - с помощью stringr::str_split() или data.table::tstrsplit()

1) с помощью stringr::str_split()

# data posted above by the asker
tmp3 <- c("1500 2", "1500 1", "1510 2", "1510 1", "1520 2", "1520 1", "1530 2", 
          "1530 1", "1540 2", "1540 1")

library(stringr)

as.integer(
  str_split(string = tmp3, 
            pattern = "[[:space:]]", 
            simplify = TRUE)[, 2] 
)
#>  [1] 2 1 2 1 2 1 2 1 2 1

simplify = TRUE говорит str_split вернуть матрицу, тогда мы можем проиндексировать матрицу для нужного столбца, поэтому часть [, 2]

2) Использование data.table::tstrsplit()

library(data.table)

as.data.table(tmp3)[, tstrsplit(tmp3, split = "[[:space:]]", type.convert = TRUE)][, V2]
#>  [1] 2 1 2 1 2 1 2 1 2 1

type.convert = TRUE здесь отвечает за преобразование в целое число, но используйте его с осторожностью для других наборов данных. Часть индексации [, V2] имеет ту же причину, что и объясненная выше для [, 2]. Здесь он выбирает второй столбец возвращаемого объекта таблицы данных, который содержит значения, требуемые запрашивающим, в виде целых чисел.

sessionInfo()
#> R version 4.0.0 (2020-04-24)
#> Platform: x86_64-w64-mingw32/x64 (64-bit)
#> Running under: Windows 10 x64 (build 18362)
#> 
#> Matrix products: default
#> 
#> locale:
#> [1] LC_COLLATE=English_United States.1252 
#> [2] LC_CTYPE=English_United States.1252   
#> [3] LC_MONETARY=English_United States.1252
#> [4] LC_NUMERIC=C                          
#> [5] LC_TIME=English_United States.1252    
#> 
#> attached base packages:
#> [1] stats     graphics  grDevices utils     datasets  methods   base     
#> 
#> loaded via a namespace (and not attached):
#>  [1] compiler_4.0.0  magrittr_1.5    tools_4.0.0     htmltools_0.4.0
#>  [5] yaml_2.2.1      Rcpp_1.0.4.6    stringi_1.4.6   rmarkdown_2.1  
#>  [9] highr_0.8       knitr_1.28      stringr_1.4.0   xfun_0.13      
#> [13] digest_0.6.25   rlang_0.4.6     evaluate_0.14

Создано 06 мая 2020 г. с помощью пакета reprex (v0.3.0)

person Valentin    schedule 06.05.2020

Более простой способ разбить 1 столбец на 2 столбца через data.table

require(data.table)  
data_ex = data.table( a = paste( sample(1:3, size=10, replace=TRUE),"-separate", sep="" ))  
data_ex[, number:=  unlist( strsplit(x=a, split="-") )[[1]], by=a]  
data_ex[, word:= unlist( strsplit(x=a, split="-") )[[2]], by=a ]
person greenbooks    schedule 30.04.2013