首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用冒号中的模式划分列

使用冒号中的模式划分列
EN

Stack Overflow用户
提问于 2020-01-22 14:20:56
回答 6查看 232关注 0票数 2

假设我有以下简化表,其中有动态列a_x (其中x是索引,例如0、1、2、3、4.)分别为b_x。a列的数量总是等于b列的数量,但是列的总数可以是动态的(并不总是3 a和3 b)。为了更清楚地说明,下面的示例描述了我的数据结构:

代码语言:javascript
复制
> d <- read.table(text = "10 20 25 0.3 0.23 0.34 
                          40 20 30 0.25 0.4 0.45")
> names(d) <- c("a_0", "a_1", "a_2", "b_0", "b_1", "b_2")
> d
   a_0 a_1 a_2  b_0  b_1  b_2
1  10  20  25   0.30 0.23 0.34
2  40  20  30   0.25 0.40 0.45

我希望将a列与相应的b列分开,并将结果保存到新的c列中。为了进行除法,我使用了transform()函数(带有硬编码的冒号),如下所示:

代码语言:javascript
复制
transform(d, c_0 = as.numeric(as.character(a_0)) / as.numeric(as.character(b_0)))

考虑到输入数据的列数并不总是相同的事实,我如何使用(可能)冒名模式自动完成这一步骤。

如能提供任何帮助,将不胜感激。

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2020-01-22 14:32:15

以下是几种方法。(1)和(1a)似乎最好,但其他方法确实显示了不同的方法。除(1a)和(2)外,它们的列名和顺序与问题相同,但如果这是一个问题,则可以很容易地加以修正。除(4a)外,不使用任何包。

1)变换

代码语言:javascript
复制
ix <- grep("a", names(d))
cbind(d, setNames(d[ix] / d[-ix], sub("a", "c", names(d)[ix])))
##   a_0 a_1 a_2  b_0  b_1  b_2       c_0      c_1      c_2
## 1  10  20  25 0.30 0.23 0.34  33.33333 86.95652 73.52941
## 2  40  20  30 0.25 0.40 0.45 160.00000 50.00000 66.66667

1a)这是(1)的一个变体;

代码语言:javascript
复制
transform(d, c = setNames(d[ix], ix-1) / d[-ix])  # ix is from above
##   a_0 a_1 a_2  b_0  b_1  b_2       c.0      c.1      c.2
## 1  10  20  25 0.30 0.23 0.34  33.33333 86.95652 73.52941
## 2  40  20  30 0.25 0.40 0.45 160.00000 50.00000 66.66667

2)将转换为长格式,执行除法,并将其转换回宽格式。

代码语言:javascript
复制
varying <- split(names(d), sub("_.*", "", names(d)))
long <- reshape(d, dir = "long", varying = varying, v.names = names(varying))
reshape(transform(long, c = a / b), dir = "wide", idvar = "id")[-1]
##     a.1  b.1       c.1 a.2  b.2      c.2 a.3  b.3      c.3
## 1.1  10 0.30  33.33333  20 0.23 86.95652  25 0.34 73.52941
## 2.1  40 0.25 160.00000  20 0.40 50.00000  30 0.45 66.66667

3)应用,我们可以转换成三维数组,然后使用apply

代码语言:javascript
复制
nr <- nrow(d)
nc <- ncol(d)
cc <- apply(array(as.matrix(d), c(nr, nc / 2, 2)), 1:2, function(x) x[1] / x[2])
colnames(cc) <- paste("c", seq(0, length = ncol(cc)), sep = "_")
cbind(d, cc)
##   a_0 a_1 a_2  b_0  b_1  b_2       c_0      c_1      c_2
## 1  10  20  25 0.30 0.23 0.34  33.33333 86.95652 73.52941
## 2  40  20  30 0.25 0.40 0.45 160.00000 50.00000 66.66667

4)将转置到d原木上,取差,再取exp转座子逆转原木转置。然后将其绑定到d。该解决方案假定所有条目都是严格正的(这是问题中的情况),这样我们就可以获取日志。

代码语言:javascript
复制
nc <- ncol(d)
cc <- t(exp(-diff(t(log(d)), nc/2)))
colnames(cc) <- paste("c", seq(0, length = ncol(cc)), sep = "_")
cbind(d, cc)
##   a_0 a_1 a_2  b_0  b_1  b_2       c_0      c_1      c_2
## 1  10  20  25 0.30 0.23 0.34  33.33333 86.95652 73.52941
## 2  40  20  30 0.25 0.40 0.45 160.00000 50.00000 66.66667

(4a) diff.zoo支持几何差,它执行除法而不是减法。(在当前版本的动物园中,diff.zoo要求输入的元素严格为正,但在动物园的开发版本中取消了这一限制。)

代码语言:javascript
复制
library(zoo)

nc <- ncol(d)
cc <- 1 / t(diff(zoo(t(d)), nc/2, arith = FALSE))
colnames(cc) <- paste("c", seq(0, length = ncol(cc)), sep = "_")
cbind(d, cc)
##     a_0 a_1 a_2  b_0  b_1  b_2       c_0      c_1      c_2
## x.1  10  20  25 0.30 0.23 0.34  33.33333 86.95652 73.52941
## x.2  40  20  30 0.25 0.40 0.45 160.00000 50.00000 66.66667
票数 4
EN

Stack Overflow用户

发布于 2020-01-22 14:24:19

我们可以从名称中删除下划线后的所有内容,然后将它们分开,然后逐个分割。

代码语言:javascript
复制
Reduce(`/`, split.default(d, gsub('_.*', '', names(d))))
#        a_0      a_1      a_2
#1  33.33333 86.95652 73.52941
#2 160.00000 50.00000 66.66667
票数 2
EN

Stack Overflow用户

发布于 2020-01-22 14:30:40

您可以使用grep查找"a“和"b”列,并在transform中将结果添加为具有良好setNames的矩阵。

代码语言:javascript
复制
transform(d, ind=setNames(d[, grep("a", names(d))] / d[, grep("b", names(d))], 
                          gsub(".*(\\D)", "", grep("a", names(d), value=T))))
#   a_0 a_1 a_2  b_0  b_1  b_2     ind.0    ind.1    ind.2
# 1  10  20  25 0.30 0.23 0.34  33.33333 86.95652 73.52941
# 2  40  20  30 0.25 0.40 0.45 160.00000 50.00000 66.66667
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59861786

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档