示例数据:
library(dplyr)
id <- rep(LETTERS[1:5], each = 10)
x <- round(runif(50, -500, 200), digits = 0)
y <- round(runif(50, -700, 700), digits = 0)
z <- round(runif(50, 250, 300), digits = 0)
df.1 <- data.frame(id = id, x = x, y = y, z = z)
> summary(df.1)
id x y z
A:10 Min. :-497.0 Min. :-665.00 Min. :251.0
B:10 1st Qu.:-283.2 1st Qu.:-349.50 1st Qu.:261.2
C:10 Median :-128.0 Median : -33.50 Median :274.5
D:10 Mean :-145.4 Mean : -39.58 Mean :275.3
E:10 3rd Qu.: -15.0 3rd Qu.: 293.25 3rd Qu.:288.0
Max. : 171.0 Max. : 696.00 Max. :299.0
我想要实现的目标是:
a - 识别x,y,z中范围最宽的列 b - 在标识的列中,根据下一行值是否大于当前行值来计算方向 - TRUE和FALSE return
即y具有最大范围
id x y z direction
1 A -320 31 251 TRUE
2 A -199 -530 276 FALSE
3 A -228 390 264 TRUE
4 A -158 363 268 TRUE
5 A -308 150 267 FALSE
6 A -47 345 261 NA
在具有最大范围的列上计算方向非常重要。在示例数据中,可能的列y始终是具有最大范围的列,但在我的实际数据中,它可以是任何列。
我想它会涉及mutate和ifelse?!但不确定我是怎么做的......我通常会使用广泛的for循环,并且上周或者两周才开始使用dplyr。试着不要再回到凌乱的for循环和严重嵌套的代码.. < / p>
非常感谢你的帮助!谢谢!
for (i in 1:length(unique(id)) {
x <-
df.1 %>%
filter(id == unique(id)[i] %>%
mutate(direction = ifelse())
assign(unique(id)[i], x)
}
答案 0 :(得分:0)
将每个id放入自己的数据框
df_list = split(df.1, df.1$id)
创建一个名为“direction”的新列,它将响应
以下的条件
- 识别x,y,z b中最宽范围的列
- 在标识的列中,根据下一行值是否大于当前行值来计算方向
- TRUE和FALSE返回
让我们编写一个函数来对一个数据框执行此操作:
foo = function(df) {
# identify column with widest range within x, y, z
sub_df = df[c("x", "y", "z")]
ranges = sapply(sub_df, max) - sapply(sub_df, min)
widest = which.max(ranges)
# see which direction it goes
direction = diff(sub_df[[widest]]) < 0
# add this as a column to whole df
df$direction = c(direction, NA)
return(df)
}
然后我们可以将此函数应用于每个数据框:
df_list = lapply(df_list foo)
在这里完成演示。为了保持紧凑,我将数据缩小了一点:
set.seed(47)
id <- rep(LETTERS[1:3], each = 6)
x <- round(runif(18, -500, 200), digits = 0)
y <- round(runif(18, -700, 700), digits = 0)
z <- round(runif(18, 250, 300), digits = 0)
df.1 <- data.frame(id = id, x = x, y = y, z = z)
df_list = split(df.1, df.1$id)
df_list = lapply(df_list, foo)
df_list
# $A
# id x y z direction
# 1 A 184 -600 262 FALSE
# 2 A -238 -44 299 TRUE
# 3 A 33 -451 274 FALSE
# 4 A 76 80 284 TRUE
# 5 A -99 22 253 TRUE
# 6 A -16 -513 269 NA
#
# $B
# id x y z direction
# 7 B -228 265 280 TRUE
# 8 B -172 -168 297 TRUE
# 9 B -120 -653 268 FALSE
# 10 B 147 -648 260 FALSE
# 11 B -403 51 283 FALSE
# 12 B -9 419 298 NA
#
# $C
# id x y z direction
# 13 C -386 348 269 TRUE
# 14 C -80 -183 293 FALSE
# 15 C -146 -45 259 TRUE
# 16 C 131 -429 289 FALSE
# 17 C -220 556 253 TRUE
# 18 C -478 -84 252 NA
我没有使用dplyr
。 dplyr
擅长许多事情,但在dplyr
中对列所依赖条件的列执行操作很困难,在上面编写类似foo
的函数更容易。也就是说,您可以稍微调整一下这个功能并执行以下操作:
library(dplyr)
library(tidyr)
df.1 %>% group_by(id) %>%
do(a = foo(.)) %>%
ungroup() %>%
unnest()
如果您希望数据框分开,最后仍然是split
,但lapply
非常简单(并且不需要额外的包),而这似乎更复杂,没有任何好处。