我有一个DataFrame,它的信息存储如下:
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)。因此,生成的数据帧应该如下所示:
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。
谢谢!
发布于 2019-02-26 04:18:51
只需要几行代码,但使用tidyverse中的函数是可能的。最大的关键是获取更宽的数据并使其变长(这是gather的工作)。然后我们找到pos == var_pos的位置,计算适当的差值,并从适当的值中减去它。separate和unite函数让我们可以转换v1 -> v和1,然后再转换回来。
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发布于 2019-02-26 04:22:52
如果你的数据帧不是太大,一个简单的for循环也可以很容易地在基数R中完成这个技巧:
# 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把它隐藏起来。
发布于 2019-02-26 05:09:57
#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使用的数据:
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)https://stackoverflow.com/questions/54873884
复制相似问题