内部使用 strsplit 的用户定义函数的语法
Posted
技术标签:
【中文标题】内部使用 strsplit 的用户定义函数的语法【英文标题】:syntax for user-defined function which uses strsplit internally 【发布时间】:2013-01-28 12:36:50 【问题描述】:我正在编写一个实用程序函数来进行一些数据格式转换,但我无法正确说明它,以便它适用于我希望它适用的数据,并返回正确形状的结果。
我有一个名为 HiRawTiny 的测试数据集,str 如下所示。 V1中的数据是char。我有一个名为 GetRank 的测试函数,它的工作是将所有字符放在“:”右侧并将它们强制转换为数字。这也在下面得到证明。我在 fn 中用于获取 strsplit 输出的列表语法列表对我来说有点不透明,坦率地说,我是通过反复试验得出的,但在传递单个值时它似乎工作正常。但是当我向它传递一个向量(一个数据框列)时,它并没有给我一个与我传递给它的向量长度相同的向量结果,而是只有一个值。
我应该怎么做才能解决这个问题?我是 R 新手(尽管几十年前我曾经使用过 S),并且怀疑我陷入了语法混乱。鉴于我正在尝试做的事情,我的函数语法是否错误?我应该考虑使用“应用”或其朋友之一来做到这一点吗?或者 fn 是否应该能够原生处理矢量输入/矢量输出?
str(HiRawTiny)
>'data.frame': 10 obs. of 7 variables:
>$ V1: chr "RANK:1" "RANK:2" "RANK:3" "RANK:4" ...
$ V2: chr
> "SOURCEID:CWC02001632398F4C" "SOURCEID:CWC020000F0D57DD6"
> "SOURCEID:CWC0200214C29872E" "SOURCEID:CWC0200163206B9F2" ...
$ V3:
> chr "TIME:01:04:2012-22:23:58" "TIME:01:04:2012-12:07:55"
> "TIME:01:04:2012-12:39:51" "TIME:02:04:2012-07:18:25" ...
$ V4: chr
> "SCORE:3142" "SCORE:3040" "SCORE:2911" "SCORE:2882" ...
$ V5: chr
> "TIEBREAK:4923864" "TIEBREAK:5787094" "TIEBREAK:766764"
> "TIEBREAK:1872936" ...
$ V6: chr "" "" "" "" ...
$ V7: chr "" ""
> "" "" ...
GetRank function(x) as.numeric(strsplit(x, split=":")[[1]][2])
GetRank(HiRawTiny[1,1]) [1] 1
GetRank(HiRawTiny[2,1]) [1] 2
GetRank(HiRawTiny[,1]) [1] 1
#"What I want is a vector of GetRank being applied to all of column 1
【问题讨论】:
提示:下次尝试粘贴dput(HiRawTiny)
的输出。我们可以将其直接读入我们的 R 会话。让帮助您更轻松。
谢谢!会做。我的控制台会话粘贴总是非常混乱,花了 20 分钟以不同的方式对其进行哈希处理,欢迎所有提示和技巧。
我的问题的根源是我无法弄清楚如何设计一个索引到列表结果列表中的表达式,以便产生可向量化的结果。从战术上讲,我采取的方向是放弃使用 strsplit ,而是使用其他矢量化字符串操作函数。这是因为我需要扩展,并且(正确或错误地)我对其他解决方案所需的回旋空间持谨慎态度。不过,这些解决方案确实为使用该语言的更高级方法提供了有趣的见解!谢谢。
【参考方案1】:
strsplit
返回一个list
。 list
的每个元素都包含分割后的字符串。您可以使用do.call
和rbind
将list
更改为matrix
,然后选择第二列,
GetRank <- function(x) as.numeric(do.call(rbind, strsplit(x, split=":"))[, 2])
GetRank(HiRawTiny$V1)
【讨论】:
谢谢,这看起来像是一种更明智(并且在维度上可扩展)的方式来索引 strsplit 结果(这是一个列表列表)。此外,我没有意识到需要通过 do.call 和 rbind 强制列表结果 - 希望它会通过魔法发生。 (我认为 R 在可能的情况下会尝试这样做,但我不应该依赖它。)为我节省了一个问题 ;-) 因为它是一个列表,而 rbind 不知道如何处理一个列表。至少不是我们想要的方式。do.call
进行函数调用,相当于 rbind(alist[[1]], alist[[2]], ..., alist[[lenght(alist)]])
【参考方案2】:
只是另一种方式(使用@Stephan 的foo
):
# split by strsplit, results in a list with the 2nd element of
# each element of the list always being the number you want.
# so pick it up using sapply with "[[" and convert it to numeric
> as.numeric(sapply(strsplit(foo, ":"), "[[", 2))
【讨论】:
有趣。 “[[”如何表示一个函数? 2 是那个函数的参数吗? 是的,是的。查看?'[['
和?InternalMethods
,也许还有getS3method("[[", "data.frame")
。
拉一个线程,整个语言就会翻滚出来......;-) 谢谢。【参考方案3】:
您需要unlist
strsplit
的结果,然后提取您感兴趣的条目。
foo <- paste("RANK:",1:10,sep="")
GetRank <- function(x)
as.numeric(unlist(strsplit(x,":"))[seq(2,2*length(x),by=2)])
GetRank(foo)
尝试将数据逐位输入函数并跟踪每个后续步骤中发生的情况。
【讨论】:
我试试看,谢谢!当我不糊涂时会报告。我试图通过对 strsplit 的结果进行双索引来执行 unlist 之类的操作 - 但我认为如果我坚持原来的公式,我需要取消其中一个索引的约束。 Stephan - 抱歉,我只能正式指出一个已接受的答案。这不是很“R”,因为总是有不止一种方法可以做某事;-) 我选择了另一种方法,因为它更接近我最初的尝试,因此我更容易理解。但是,如果有办法接受 2 个答案,请告诉我。 ta 没问题。无论如何,@Luciano 的解决方案更漂亮 ;-)以上是关于内部使用 strsplit 的用户定义函数的语法的主要内容,如果未能解决你的问题,请参考以下文章
R语言使用sapply函数抽取strsplit分裂后的结果数据并使用cbind纵向合并到dataframe数据列中使用order函数对dataframe数据行进行排序
R语言使用quantile函数计算评分值的分位数(20%40%60%80%)使用逻辑操作符将对应的分位区间(quantile)编码为分类值生成新的字段strsplit函数将学生的名和姓拆分