首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >根据条件替换列集合中的值

根据条件替换列集合中的值
EN

Stack Overflow用户
提问于 2019-03-07 10:16:41
回答 3查看 51关注 0票数 1

我有一个这样的数据帧

代码语言:javascript
复制
id  v1  v2  v3  v4  v5  pos
1   11  12  11  10  10  3
2   17  11  22  40  23  4
1   11  22  50  10  10  2

我想根据与pos相关的条件来更改它的值,以获取:

代码语言:javascript
复制
id  v1  v2  v3  v4  v5  pos
1   11  12  12  12  12  3
2   17  11  22  22  22  4
1   11  11  11  11  11  2

因此,基本上,值获取前一个值,变量pos定义了我们应该从哪里开始。

谢谢!

EN

回答 3

Stack Overflow用户

发布于 2019-03-07 10:55:57

一种使用一些索引的方法,这应该在运行时间上是有效的。

然而,由于制作了与输入数据相同大小的副本,因此在内存方面效率不是很高:

代码语言:javascript
复制
vars <- paste0("v",1:5)
nv <- dat[vars][cbind(seq_len(nrow(dat)), dat$pos-1)]
ow <- col(dat[vars]) >= dat$pos
dat[vars][ow] <- nv[row(ow)[ow]]

#  id v1 v2 v3 v4 v5 pos
#1  1 11 12 12 12 12   3
#2  2 17 11 22 22 22   4
#3  1 11 11 11 11 11   2

说明:

获取感兴趣的变量:

代码语言:javascript
复制
vars <- paste0("v",1:5)

获取要覆盖每行的新值:

代码语言:javascript
复制
nv <- dat[vars][cbind(seq_len(nrow(dat)), dat$pos-1)]

创建要覆盖的单元格的逻辑矩阵

代码语言:javascript
复制
ow <- col(dat[vars]) >= dat$pos

使用行标识符覆盖单元格以选取适当的值。

代码语言:javascript
复制
dat[vars][ow] <- nv[row(ow)[ow]]

使用更大的数据集进行快速比较计时:

代码语言:javascript
复制
dat <- dat[rep(1:3,1e6),]

# indexing
#   user  system elapsed 
#   1.36    0.31    1.68 

# apply
#   user  system elapsed 
#  77.30    0.83   78.41 

# gather/spread
#   user  system elapsed 
# 293.43    3.64  299.10
票数 2
EN

Stack Overflow用户

发布于 2019-03-07 10:41:38

这里有一个关于gatherspread的想法。

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

dat2 <- dat %>%
  rowid_to_column() %>%
  gather(v, value, starts_with("v")) %>%
  group_by(rowid) %>%
  mutate(value = ifelse(row_number() >= (pos - 1), nth(value, (pos - 1)[[1]]), value)) %>%
  spread(v, value) %>%
  ungroup() %>%
  select(names(dat))

dat2
# # A tibble: 3 x 7
#      id    v1    v2    v3    v4    v5   pos
#   <int> <int> <int> <int> <int> <int> <int>
# 1     1    11    12    12    12    12     3
# 2     2    17    11    22    22    22     4
# 3     1    11    11    11    11    11     2

DATA

代码语言:javascript
复制
dat <- read.table(text = "id  v1  v2  v3  v4  v5  pos
1   11  12  11  10  10  3
2   17  11  22  40  23  4
1   11  22  50  10  10  2",
                  header = TRUE)
library(tidyverse)
票数 1
EN

Stack Overflow用户

发布于 2019-03-07 10:47:13

从base R使用apply

代码语言:javascript
复制
data.frame(t(apply(df, 1, function(x) 
     c(x[1:x["pos"]], rep(x[x["pos"]], ncol(df) - x["pos"] - 2), x['pos']))))

#  X1 X2 X3 X4 X5 X6
#1  1 11 12 12 12  3
#2  2 17 11 22 22  4
#3  1 11 11 11 11  2
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55035030

复制
相关文章

相似问题

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