IT TIP

data.table 열에서 텍스트 문자열 분할

itqueen 2020. 10. 29. 20:20
반응형

data.table 열에서 텍스트 문자열 분할


CSV 파일의 데이터를 a로 읽은 data.table다음 한 열의 텍스트를 여러 개의 새 열로 분할 하는 스크립트가 있습니다. 현재이 작업을 수행하기 위해 lapplystrsplit함수를 사용 하고 있습니다. 예를 들면 다음과 같습니다.

library("data.table")
df = data.table(PREFIX = c("A_B","A_C","A_D","B_A","B_C","B_D"),
                VALUE  = 1:6)
dt = as.data.table(df)

# split PREFIX into new columns
dt$PX = as.character(lapply(strsplit(as.character(dt$PREFIX), split="_"), "[", 1))
dt$PY = as.character(lapply(strsplit(as.character(dt$PREFIX), split="_"), "[", 2))

dt 
#    PREFIX VALUE PX PY
# 1:    A_B     1  A  B
# 2:    A_C     2  A  C
# 3:    A_D     3  A  D
# 4:    B_A     4  B  A
# 5:    B_C     5  B  C
# 6:    B_D     6  B  D 

열 위의 예에서 PREFIX두 개의 새로운 열로 분할 PX하고 PY은 "_"캐릭터는.

이것이 잘 작동하지만 .NET을 사용하여 더 나은 (더 효율적인) 방법이 있는지 궁금합니다 data.table. 내 실제 데이터 세트에는 1,000 만 개 이상의 행이 있으므로 시간 / 메모리 효율성이 정말 중요합니다.


최신 정보:

@Frank의 제안에 따라 더 큰 테스트 케이스를 만들고 제안 된 명령을 사용했지만 stringr::str_split_fixed원래 방법보다 훨씬 오래 걸립니다.

library("data.table")
library("stringr")
system.time ({
    df = data.table(PREFIX = rep(c("A_B","A_C","A_D","B_A","B_C","B_D"), 1000000),
                    VALUE  = rep(1:6, 1000000))
    dt = data.table(df)
})
#   user  system elapsed 
#  0.682   0.075   0.758 

system.time({ dt[, c("PX","PY") := data.table(str_split_fixed(PREFIX,"_",2))] })
#    user  system elapsed 
# 738.283   3.103 741.674 

rm(dt)
system.time ( {
    df = data.table(PREFIX = rep(c("A_B","A_C","A_D","B_A","B_C","B_D"), 1000000),
                     VALUE = rep(1:6, 1000000) )
    dt = as.data.table(df)
})
#    user  system elapsed 
#   0.123   0.000   0.123 

# split PREFIX into new columns
system.time ({
    dt$PX = as.character(lapply(strsplit(as.character(dt$PREFIX), split="_"), "[", 1))
    dt$PY = as.character(lapply(strsplit(as.character(dt$PREFIX), split="_"), "[", 2))
})
#    user  system elapsed 
#  33.185   0.000  33.191 

So the str_split_fixed method takes about 20X times longer.


Update: From version 1.9.6 (on CRAN as of Sep'15), we can use the function tstrsplit() to get the results directly (and in a much more efficient manner):

require(data.table) ## v1.9.6+
dt[, c("PX", "PY") := tstrsplit(PREFIX, "_", fixed=TRUE)]
#    PREFIX VALUE PX PY
# 1:    A_B     1  A  B
# 2:    A_C     2  A  C
# 3:    A_D     3  A  D
# 4:    B_A     4  B  A
# 5:    B_C     5  B  C
# 6:    B_D     6  B  D

tstrsplit() basically is a wrapper for transpose(strsplit()), where transpose() function, also recently implemented, transposes a list. Please see ?tstrsplit() and ?transpose() for examples.

See history for old answers.


I add answer for someone who do not use data.table v1.9.5 and also want an one line solution.

dt[, c('PX','PY') := do.call(Map, c(f = c, strsplit(PREFIX, '-'))) ]

Using splitstackshape package:

library(splitstackshape)
cSplit(df, splitCols = "PREFIX", sep = "_", direction = "wide", drop = FALSE)
#    PREFIX VALUE PREFIX_1 PREFIX_2
# 1:    A_B     1        A        B
# 2:    A_C     2        A        C
# 3:    A_D     3        A        D
# 4:    B_A     4        B        A
# 5:    B_C     5        B        C
# 6:    B_D     6        B        D

With tidyr the solution is:

separate(df,col = "PREFIX",into = c("PX", "PY"), sep = "_")

What about ??? fread(text = dt$PREFIX )

참고URL : https://stackoverflow.com/questions/18154556/split-text-string-in-a-data-table-columns

반응형