楼主: king64
2575 9

[问答] 求教:如何分割一个很大的字符矢量? [推广有奖]

  • 1关注
  • 11粉丝

已卖:1336份资源

副教授

31%

还不是VIP/贵宾

-

威望
0
论坛币
1139 个
通用积分
119.2433
学术水平
48 点
热心指数
54 点
信用等级
42 点
经验
8328 点
帖子
318
精华
0
在线时间
1159 小时
注册时间
2008-2-7
最后登录
2023-7-17

楼主
king64 发表于 2016-1-6 12:01:27 |AI写论文

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币
有一个很大的字符矢量,约1000万个元素,其中第一个元素是“XXX”,以后大约每隔13个元素左右再出现一次“XXX”(间隔没有规律)。我想这个大矢量分割成许多小矢量,截取时要求是每个小矢量第一个元素为“XXX”,最后一个元素截止在下一个“XXX”之前。同时,想把这些小矢量保存在同一个list中。
“XXX”的位置很容易获取!id <- which(z=="XXX")
请问如何操作才能有效率?


先谢谢了!

二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:list 最后一个 IST 分割字符矢量

本帖被以下文库推荐

沙发
万人往LVR 在职认证  发表于 2016-1-6 14:25:44
  1. pos <- which(z=="XXX")
  2. len <- c(diff(pos),length(z)-pos[length(pos)]+1)
  3. gfun <- function(i){return(z[pos[i]:(pos[i]+len[i]-1)])}
  4. results <- lapply(1:length(pos),gfun)
复制代码
已有 1 人评分论坛币 收起 理由
admin_kefu + 20 热心帮助其他会员

总评分: 论坛币 + 20   查看全部评分

藤椅
king64 发表于 2016-1-6 15:11:39
万人往LVR 发表于 2016-1-6 14:25
谢谢!
function(i)用法学习了!谢谢!

板凳
cheetahfly 在职认证  发表于 2016-1-6 16:06:51
  1. split(z,cumsum(z=="XXX"))
复制代码
已有 2 人评分论坛币 学术水平 收起 理由
万人往LVR + 2 精彩帖子
admin_kefu + 10 热心帮助其他会员

总评分: 论坛币 + 10  学术水平 + 2   查看全部评分

报纸
万人往LVR 在职认证  发表于 2016-1-6 17:56:40
cheetahfly 发表于 2016-1-6 16:06
你好,我看了split的函数说明,但是没发现cumsum这个参数,可以告诉我参数说明在哪里吗?

地板
suimong 发表于 2016-1-6 18:18:47
万人往LVR 发表于 2016-1-6 17:56
你好,我看了split的函数说明,但是没发现cumsum这个参数,可以告诉我参数说明在哪里吗?
cumsum不是参数而是函数(cumulative sum)。
这里cumsum(z=="XXX")对应的split的参数是f,也就是用来确定分组(factor)的表达式。
简单的测试了一下,你的写法性能上是split的2倍以上,组数越多差距越大。当然了split胜在简洁

7
万人往LVR 在职认证  发表于 2016-1-7 09:36:05
suimong 发表于 2016-1-6 18:18
cumsum不是参数而是函数(cumulative sum)。
这里cumsum(z=="XXX")对应的split的参数是f,也就是用来确 ...
谢谢!

8
cheetahfly 在职认证  发表于 2016-1-7 22:34:44
suimong 发表于 2016-1-6 18:18
cumsum不是参数而是函数(cumulative sum)。
这里cumsum(z=="XXX")对应的split的参数是f,也就是用来确 ...
首先要感谢万人往LVR,他代码中的lapply(1:length(pos),gfun)是我所不会的,且用起来很方便。
另外,我主要想讨论一下代码的效率问题,因为我测试的结果不太一样。
我在理顺了“
万人往LVR”代码的逻辑之后,尝试按照他的逻辑稍微修改了一下,自我感觉可能更顺一些,(用两个向量一个代表分割项开始的位置,另一个代表结束的位置,没有必要另一个代表长度)如下:
  1. pos.begin <- which(z=="xxx")
  2. pos.end <- c((pos.begin-1)[-1], length(z))
  3. ff <- function(i) {return(z[pos.begin[i]:pos.end[i]])};
  4. result <- lapply(1:length(pos.begin), ff)
复制代码
然后我模拟1000万个变量:
  1. z <- sample(c("xxx","a","b","c"),10000000,replace = T)
  2. z[1]<- "xxx"
复制代码
以下是我测试的环境:
CPU:英特尔酷睿2双核E6750 @2.66GHz (买了快10年了)
OS:win7 32位
内存:4G
以下是测试结果:(先后顺序是:原“万人往LVR”的代码,我修改后的代码,split()函数)

test.PNG
可以看到split的效率是三者中相对比较高的。

我改变模拟z的方法,增加变量,减少子向量的数目
  1. z <- sample(c("xxx",1:100),10000000,replace = T)
  2. z[1]<- "xxx"
复制代码
再测试一遍:(顺序不变)
test2.PNG
发现结果完全颠倒了,得出了与
suimong同学相同的结论。
我没再进一步测试,但是否已经可以得出这样的结论:当要分割成的子向量数越多(分割次数越多)时,多行代码与split函数耗时均增加,但多行代码增加得更快;当
要分割成的子向量数越少时多行代码与split函数耗时均减少,但多行代码减少的速度也要快得多!

我这样的结论能否成立,请大神帮忙看看,谢谢!

(下面的图重复了,勿理,删不掉)

test.PNG (16.61 KB)

test.PNG

已有 1 人评分论坛币 收起 理由
admin_kefu + 40 热心帮助其他会员

总评分: 论坛币 + 40   查看全部评分

9
suimong 发表于 2016-1-8 12:23:52
cheetahfly 发表于 2016-1-7 22:34
首先要感谢万人往LVR,他代码中的lapply(1:length(pos),gfun)是我所不会的,且用起来很方便。
另外,我主 ...
谢谢你的回复,不然我还发现不了我测试里的问题~
重新写了一下:
先生成测试数据
  1. # 生成测试数据,1000万个随机字母,分别插入一千,一万,十万,一百万个"XXX"
  2. s_base <- sample(letters, size = 1e7, replace = TRUE)
  3. s_anchor <- lapply(10^(3:6), function(x) rep("XXX", x))

  4. s <- lapply(s_anchor, function(x) {
  5.   out <- sample(c(x, s_base))
  6.   c("XXX", out)
  7. })
复制代码


定义函数
  1. # 万人往LVR的方法
  2. fun_2 <- function(z) {
  3.   pos <- which(z=="XXX")
  4.   len <- c(diff(pos),length(z)-pos[length(pos)]+1)
  5.   gfun <- function(i){return(z[pos[i]:(pos[i]+len[i]-1)])}
  6.   lapply(1:length(pos),gfun)
  7. }
复制代码

  1. # cheetahfly的方法
  2. fun_4 <- function(v) {
  3.   split(v, cumsum(v == "XXX"))
  4. }
复制代码


测试
  1. library(microbenchmark)
  2. (bm_fun_2 <- lapply(s, function(x) microbenchmark(fun_2(x), times = 10L)))

  3. (bm_fun_4 <- lapply(s, function(x) microbenchmark(fun_4(x), times = 10L)))
复制代码


测试的结果越来越有趣了:
图像 5.png
在组数为10万时,@万人往LVR的方法仍旧速度占优,但是当组数为100万时(这时候其实更接近原题主的实际情况,因为题主说XXX大概每隔13个出现一次),@万人往LVR的方法性能有大幅下降,但@cheetahfly的方法居然比10万组时更快!

10
king64 发表于 2016-1-10 09:23:00
谢谢诸位了!

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
加好友,备注cda
拉您进交流群
GMT+8, 2026-1-9 17:33