我有一个关于R的特定编程问题。 我想在整个数据集上应用自定义函数,但是该函数中的值与其所属的组相比应该有所变化。这是一个与我正在使用的数据集相似的数据集
set.seed(123)
df <- data.frame(group = c(rep("one", 10), rep("two", 9), rep("three", 11)),
slot = c(1:10, 1:9, 1:11),
x = sample(100, 30))
和功能
RI_fun <- function(x, y) {
((x - y)/ y) * 100
}
实际数据集较大,但结构相同。关于真实数据集的一些信息:这是一个样本(组)上的一系列测量值(插槽),我希望自定义函数(RI_fun)中的第一个测量值(插槽== 1)为y
我想创建一个新列作为自定义函数的输出,其中x = df $ x,y是每个组的df $ slot == 1的x值。
我试图进行for循环,但没有成功。我的想法是使y值成为if else语句,在该语句中检查df $ group并在刚刚检查过的slot == 1和group == group处应用df $ x。
这是我的尝试:
for (i in seq_along(df$group)) {
RI[i] = RI_fun(x = df$x[i],
y = (ifelse(df$group == df$group[i],
df$x[df$slot == 1 & df$group == df$group[i]],
NA)))
但是输出是:
[1] 0.00000 172.41379 41.37931 196.55172 213.79310 -82.75862 72.41379 186.20690 75.86207 44.82759 NA
[12] NA NA NA NA NA NA NA NA NA NA NA
[23] NA NA NA NA NA NA NA NA
当我手动检查输出应该是什么时,它表明for循环是正确的,直到[11]都不再起作用。我已经尝试过其他一些与此循环类似的for循环,但这是我最接近所需输出的循环。
您所获得的任何帮助将不胜感激。如果我不够清楚,请询问,我会尽力使其更加清晰。
答案 0 :(得分:1)
很好的问题,并且格式很好,带有可重现的示例!恭喜!
在R中,通常不需要使用循环。 R本质上是向量化的,因此我们可以用向量表达自己。转到data.frames的想法是相同的,并添加了包dplyr
,我们获得了一些简单的功能。
首先,我演示您想要的内容:
library(dplyr)
df %>% group_by(group) %>%
mutate(y=x[slot==1])
as.data.frame(.Last.value)
group slot x y
1 one 1 30 30
2 one 2 72 30
3 one 3 88 30
4 one 4 5 30
5 one 5 55 30
6 one 6 42 30
7 one 7 11 30
8 one 8 53 30
9 one 9 73 30
10 one 10 87 30
11 two 1 52 52
12 two 2 82 52
13 two 3 78 52
14 two 4 59 52
15 two 5 12 52
16 two 6 95 52
17 two 7 1 52
18 two 8 70 52
19 two 9 66 52
20 three 1 69 69
21 three 2 79 69
22 three 3 80 69
23 three 4 21 69
24 three 5 94 69
25 three 6 75 69
26 three 7 25 69
27 three 8 15 69
28 three 9 74 69
29 three 10 31 69
30 three 11 43 69
因此,我们可以确认我们获得了正确的x
和y
值。尝试删除行group_by
,看看会发生什么。
对我们获得相关的x
和y
值感到满意,请插入您的函数:
df %>% group_by(group) %>%
mutate(RI=RI_fun(x, x[slot==1]))
如果您确实尝试删除了group_by
行,则会出现错误。这是因为mutate
要使用一个值,整个矢量(列)使用1或该列中每个元素使用一个值。那么,如果每个组有多个插槽== 1,会发生什么情况?好吧,您必须决定如何处理偏离您需求的情况。
编辑:
for循环无法按预期运行的原因是由于y处的ifelse
。只需替换为
for (i in seq_along(df$group)) {
RI[i] = RI_fun(x = df$x[i],
y = df$x[df$slot == 1 & df$group == df$group[i]])
}
它应该可以正常工作。
这是由于ifelse
是矢量化的;对于test(第一个)参数(df$group == df$group[i]
)中的每个元素,它将在yes(第二个)或no(第三个)元素中返回相应的元素。
答案 1 :(得分:0)
问题出在ifelse语句上。当您调用ifelse(df $ group == df $ group [i] ...)时,只要df $ group [i]!= df $ group [1],它就会返回false。它返回第一个比较的结果。据我所知,您不需要ifelse。以下代码对我有用(尽管您应该进行手动检查以确保它是正确的)。
df <- data.frame(group = c(rep("one", 10), rep("two", 9), rep("three", 11)),
slot = c(1:10, 1:9, 1:11),
x = sample(100, 30))
RI_fun <- function(x, y) {
((x - y)/ y) * 100
}
RI <- rep(NA, 30)
for (i in seq_along(df$group)) {
RI[i] = RI_fun(x = df$x[i],
y = (df$x[df$slot == 1 & df$group == df$group[i]]))
}
RI