首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >基于位置的减法常量

基于位置的减法常量
EN

Stack Overflow用户
提问于 2019-02-26 04:09:11
回答 4查看 70关注 0票数 2

我有一个DataFrame,它的信息存储如下:

代码语言:javascript
运行
复制
id  store   v1  v2  v3  v4  v5  pos
1   A       5   5   7   7   7   3
2   B       1   1   1   4   5   4

我想根据变量位置减去值,例如id =1,位置是3,所以我想从v3,v4和v5中减去一个常数,等于V3和v2之间的差值2 (7-5)。因此,生成的数据帧应该如下所示:

代码语言:javascript
运行
复制
id  store   v1  v2  v3  v4  v5  pos
1   A       5   5   5   5   5   3
2   B       1   1   1   1   2   4

对于第二行,位置是4so (V4-V3 = 3),所以我们从位于位置4和5的变量减去3。

谢谢!

EN

回答 4

Stack Overflow用户

发布于 2019-02-26 04:18:51

只需要几行代码,但使用tidyverse中的函数是可能的。最大的关键是获取更宽的数据并使其变长(这是gather的工作)。然后我们找到pos == var_pos的位置,计算适当的差值,并从适当的值中减去它。separateunite函数让我们可以转换v1 -> v1,然后再转换回来。

代码语言:javascript
运行
复制
library(tidyverse)
dat %>%
    gather(variable, value, starts_with('v')) %>% # wide to long
    separate(variable, c('variable', 'var_pos'), sep = 1) %>% # v1 -> v, 1
    group_by(id) %>%
    mutate(var_diff = value[var_pos == pos] - value[var_pos == (pos - 1)]) %>%
    mutate(value = ifelse(var_pos >= pos, value - var_diff, value)) %>% # subtract
    unite(variable, variable, var_pos, sep = '') %>% # v,1 -> v1
    select(-var_diff) %>%
    spread(variable, value) # long to wide

    id store   pos    v1    v2    v3    v4    v5
  <int> <chr> <int> <int> <int> <int> <int> <int>
1     1 A         3     5     5     5     5     5
2     2 B         4     1     1     1     1     2
票数 2
EN

Stack Overflow用户

发布于 2019-02-26 04:22:52

如果你的数据帧不是太大,一个简单的for循环也可以很容易地在基数R中完成这个技巧:

代码语言:javascript
运行
复制
# Load your data frame
df <- read.table(header = TRUE, text = "
id  store   v1  v2  v3  v4  v5  pos
1   A       5   5   7   7   7   3
2   B       1   1   1   4   5   4")

# Run through all rows
for (i in seq_len(nrow(df))) {
  p <- df$pos[i]  # Get position
  dif <- df[i, paste0("v", p)]  - df[i, paste0("v", p - 1)]  # Compute difference
  cols <- paste0("v", seq(p, 5))  # Construct colnames to subtract dif from
  df[i, cols] <- df[i, cols] - dif  # Do the subtraction
}
print(df)
#  id store v1 v2 v3 v4 v5 pos
#1  1     A  5  5  5  5  5   3
#2  2     B  1  1  1  1  2   4

当然,这段代码依赖于一些假设,即您的实际生活数据看起来与这里的数据非常相似。如果不是,我想代码很容易被采用。

如果你讨厌R中的for-loops,你可以把它包装成一个函数,然后用apply把它隐藏起来。

票数 1
EN

Stack Overflow用户

发布于 2019-02-26 05:09:57

代码语言:javascript
运行
复制
#select v columns (v1, v2, ..., v5)
vs <- df[grep('^v', names(df))]
# compute differences (in this case, the vector c(2, 3))
diffs <- vs[cbind(1:nrow(df), df$pos)] - vs[cbind(1:nrow(df), df$pos - 1)]
# subtract diffs from vs if the column is >= pos
df[grep('^v', names(df))] <- vs - diffs*(col(vs) >= df$pos)


df
#   id store v1 v2 v3 v4 v5 pos
# 1  1     A  5  5  5  5  5   3
# 2  2     B  1  1  1  1  2   4

使用的数据:

代码语言:javascript
运行
复制
df <- read.table(text = '
id  store   v1  v2  v3  v4  v5  pos
1   A       5   5   7   7   7   3
2   B       1   1   1   4   5   4
', header = T)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54873884

复制
相关文章

相似问题

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