R: o'zgaruvchan uzunlikdagi mag'lubiyatning bir qismini chiqaring

Menda ma'lum qismlarni ajratmoqchi bo'lgan satrlar (juda katta, millionlab qatorlar) ro'yxati bor.

Avvaliga mag'lubiyatni nuqta-vergulga bo'linib, keyin ma'lum qismlarga ajratib qo'ydim. Bu biroz murakkablashdi, chunki ba'zida 3, ba'zan esa bir qatorda 4 ta segment mavjud. Lekin menga qiziqqan qismlar doimo oxirgi va ikkinchi va oxirgi qismdir.

Misol kodi:

dataStr = c("secAlways;  secExtr1; secExtr2",
            "secSometimes;  secAlways;  secExtr1; secExtr2",
            "secSometimes;  secAlways;  secExtr1; secExtr2",
            "secAlways;  secExtr1; secExtr2",
            "secAlways;  secExtr1; secExtr2",
            "secAlways;  secExtr1; secExtr2",
            "secSometimes;  secAlways;  secExtr1; secExtr2",
            "secAlways;  secExtr1; secExtr2",
            "secAlways;  secExtr1; secExtr2",
            "secAlways;  secExtr1; secExtr2")

splStr <- strsplit(dataStr, ";")
extr1 <- list()
extr2 <- list()

for (i in 1:length(splStr)) {
  extr1[i] <- head( tail(splStr[[i]], n=2), n=1)
  extr2[i] <- tail(splStr[[i]], n = 1)
}

Bu ishlaydi, lekin juda sekin. Buni tezroq qilish uchun qandaydir g'oyalar uchun minnatdor bo'lardim. Buni apply bilan bajarish mumkin deb o'ylayman, lekin boshimni o'rab qo'yolmadim.


Masala, agar bu savol. O'ylaymanki, bu bir-biridan farq qiladi, chunki men so'nggi ikki elementni chiqarishni istayman va bo'limlar soni farq qiladi. Bundan tashqari, hali haqiqiy dunyo namunasida ishlash uchun olgan vapply bilan echimni topmadim.

0

6 javoblar

Menimcha, bu erda regexp-dan foydalanishingiz mumkin:

sub(".+; (.+?); (.+?)$", "\\2", dataStr)

Bu oxirgi elementni qamrab oladi.

sub(".+; (.+?); (.+?)$", "\\1", dataStr)

Ushbu element oxirgi elementdan oldin qatnashadi.

3
qo'shib qo'ydi
Haqiqiy dunyo namunasi bo'yicha 27 barobar ko'paytirildi.
qo'shib qo'ydi muallif ulima2_, manba

stringr echimidan so'z

stringr::word(dataStr, -2, -1,  sep = ';')

Keyin ularni strsplit yordamida 2 ta turli xil so'zlar, ya'ni

do.call(rbind, strsplit(trimws(word(dataStr, -2, -1,  sep = ';')), '; '))
#      [,1]       [,2]      
# [1,] "secExtr1" "secExtr2"
# [2,] "secExtr1" "secExtr2"
# [3,] "secExtr1" "secExtr2"
# [4,] "secExtr1" "secExtr2"
# [5,] "secExtr1" "secExtr2"
# [6,] "secExtr1" "secExtr2"
# [7,] "secExtr1" "secExtr2"
# [8,] "secExtr1" "secExtr2"
# [9,] "secExtr1" "secExtr2"
#[10,] "secExtr1" "secExtr2"
2
qo'shib qo'ydi
Menimcha, bu ishni qilmaydi: ikkala bo'lim ham bir xil hujayradan birgadir.
qo'shib qo'ydi muallif ulima2_, manba
Katta, hozir ishlaydi - rahmat! Ro'yxatga olish yechimi, asosan, tezroq.
qo'shib qo'ydi muallif ulima2_, manba
Tahrirlangan. Etakchi/orqa bo'shliqlarni olib tashlash uchun trimws dan foydalanar edim
qo'shib qo'ydi muallif Sotos, manba
Ha, men buni kutgan edim, lekin men bir oz regex-blindman, shuning uchun ularni iloji boricha iloji yo'q
qo'shib qo'ydi muallif Sotos, manba

We can use stringi to make this faster along with vapply

library(stringi)
vapply(stri_split(dataStr, regex=';\\s*'), function(x) tail(x, 2), character(2))
1
qo'shib qo'ydi
Bu misolda bu erda ishlaydi, lekin mening haqiqiy misolimda muvaffaqiyatsiz tugadi: Vapplydagi xato (splStr, funktsiya (x) quyruq (x, 2), belgi (2)): qiymatlar uzunligi 2 bo'lishi kerak, lekin FUN ( X [[5487]]) natijasi uzunligi 1
qo'shib qo'ydi muallif ulima2_, manba
@ ulima2_ Sizda kamida ikkita kasali borligi va nima qilish kerakligi aniq emas
qo'shib qo'ydi muallif akrun, manba

Buning tezroq bo'lishi mumkin:

str_list <- lapply(splStr, tail, 2)
do.call(rbind, str_list)

      [,1]         [,2]       
 [1,] "  secExtr1" " secExtr2"
 [2,] "  secExtr1" " secExtr2"
 [3,] "  secExtr1" " secExtr2"
 [4,] "  secExtr1" " secExtr2"
 [5,] "  secExtr1" " secExtr2"
 [6,] "  secExtr1" " secExtr2"
 [7,] "  secExtr1" " secExtr2"
 [8,] "  secExtr1" " secExtr2"
 [9,] "  secExtr1" " secExtr2"
[10,] "  secExtr1" " secExtr2"
0
qo'shib qo'ydi
Xo'sh, xuddi shunday. splStr - split dataStr.
qo'shib qo'ydi muallif JohannesNE, manba
Regex usuli aslida tezroq (hech bo'lmaganda ushbu misolda o'rnatilgan).
qo'shib qo'ydi muallif JohannesNE, manba

Oxirgi va ikkinchi so'nggi segmentlar har doim bir xil sonli belgilar bo'lishini inobatga olsak, bu stringi kutubxonasi bilan quyidagi tarzda erishish mumkin.

Men sizni ikkita ro'yxatni chiqqani kabi qabul qildim.

library(stringi)

dataStr = c("secAlways;  secExtr1; secExtr2",
            "secSometimes;  secAlways;  secExtr1; secExtr2",
            "secSometimes;  secAlways;  secExtr1; secExtr2",
            "secAlways;  secExtr1; secExtr2",
            "secAlways;  secExtr1; secExtr2",
            "secAlways;  secExtr1; secExtr2",
            "secSometimes;  secAlways;  secExtr1; secExtr2",
            "secAlways;  secExtr1; secExtr2",
            "secAlways;  secExtr1; secExtr2",
            "secAlways;  secExtr1; secExtr2")

extr1 <- as.list(stringi::stri_sub(dataStr, from=-18, to=-11))
extr2 <- as.list(stringi::stri_sub(dataStr, from= -8))
0
qo'shib qo'ydi
Afsuski, ular men uchun xuddi shunday holatlar emas, bu erda noto'g'ri misol uchun uzr so'rayman.
qo'shib qo'ydi muallif ulima2_, manba
> str_list <- lapply(dataStr, tail, 2)

> do.call(rbind, str_list)


      [,1]                                           
[1,] "secAlways;  secExtr1; secExtr2"               
[2,] "secSometimes;  secAlways;  secExtr1; secExtr2"
[3,] "secSometimes;  secAlways;  secExtr1; secExtr2"
[4,] "secAlways;  secExtr1; secExtr2"               
[5,] "secAlways;  secExtr1; secExtr2"               
[6,] "secAlways;  secExtr1; secExtr2"               
[7,] "secSometimes;  secAlways;  secExtr1; secExtr2"
[8,] "secAlways;  secExtr1; secExtr2"               
[9,] "secAlways;  secExtr1; secExtr2"               
[10,] "secAlways;  secExtr1; secExtr2"  

Buning ishlashiga ishonchim komil emasmi?

0
qo'shib qo'ydi