拆分大型数据集中的串联数据。寻求计算时间的改进

问题描述 投票:0回答:2

我正在处理一个大型数据框,其中包含一个串联向量,该向量中包含几条信息。我需要提取这些值进行分析,这可以使用 substr() 函数来完成,但观察结果的长度不同,这使得这不理想。虽然我有一些工作代码,但数据集的大小意味着需要相当长的时间来处理,并且想知道是否有更好的方法。

例如8位数据点“97110770” 包含信息

  • 时间:97 人:11077 地点:0

但有些值是 9 位数字,例如“114123411” 将会有:

  • 时间:114,人数:12341,地点:1

为了解决这个问题,我想到在较小的变量前面添加一个“0”,这样它们的长度就相同(时间值后面的数字一致,所以它可以正常工作)并想出了以下代码:

(数据框:

data
,感兴趣的向量:
speakerid

congv <- vector(mode = "numeric")
memberidv <- vector(mode = "numeric")
chamberv <- vector(mode = "numeric")

for (i in 1:length(data$speakerid)) {
  if(nchar(data$speakerid[i]) == 8) {
    data$speakerid[i] = paste0("0", data$speakerid[i])
  }
  
  congv <- append(congv, substr(data$speakerid[i], 1, 3) )
  memberidv <- append(memberidv, substr(data$speakerid[i], 4, 8))
  chamberv <- append(chamberv, substr(data$speakerid[i], 9, 9))
}

data <- cbind(data, cong = congv, memberid = memberidv, chamber = chamberv)
data <- select(data, "memberid", "count", "chamber", "cong")

rm(list = c("congv", "memberidv", "chamberv"))

这可行,但是由于数据的大小(超过 100k 个观察值),它花费的时间比我想要的要长得多(因为我稍后可能需要包含更多数据),我想知道是否有更有效的方法这样做(也许不使用 for-if 循环?)

如果没有,我对 R 相当陌生,希望您能提供有关我的代码的任何其他提示,谢谢!

Example dataframe:

speakerid = c(97110770, 114123411, 93123770, 112123410, 93123770)
count = c(12, 3, 4, 0, 4)
data = data.frame(speakerid, count)
r concatenation large-data
2个回答
1
投票

尝试使用

mapply
并使用
sprintf
添加前导零。

> cbind(data, `colnames<-`(mapply(substr, list(sprintf('%09d', data$speakerid)), 
+                                 c(1, 4, 9), c(3, 8, 9)),
+                          c('cong', 'memberid', 'chamber')))
  speakerid count cong memberid chamber
1  97110770    12  097    11077       0
2 114123411     3  114    12341       1
3  93123770     4  093    12377       0
4 112123410     0  112    12341       0
5  93123770     4  093    12377       0
----

数据:

> dput(data)
structure(list(speakerid = c("097110770", "114123411", "093123770", 
"112123410", "093123770"), count = c(12, 3, 4, 0, 4)), row.names = c(NA, 
-5L), class = "data.frame")

0
投票

这里有一个

tidyverse
选项,它添加前导零,分解字符串并在短短几行内创建新列,没有循环或中间变量:

library(tidyverse)

data %>%
  mutate(sid = ifelse(speakerid < 1e8, paste0('0', speakerid), speakerid)) %>%
  separate(sid, sep = c(4, 8), into = c('time', 'person', 'place'))
#>   speakerid count time person place
#> 1  97110770    12  097  11077     0
#> 2 114123411     3  114  12341     1
#> 3  93123770     4  093  12377     0
#> 4 112123410     0  112  12341     0
#> 5  93123770     4  093  12377     0
© www.soinside.com 2019 - 2024. All rights reserved.