R将代码应用于不同的因素或级别

时间:2014-06-20 05:06:14

标签: r apply

下面是生成数据以演示问题的代码。

con <- textConnection('
  Nu Na Vo
 100  A 60
 103  A 2
 104  A 2
 106  A 5
 107  A 1
 108  A 1
 112  A 50
 100  B 1
 108  B 4
 109  B 2
 120  B 30
 109  C 40
                      ')
tt <- read.table(con, header = T)
close(con)
test <- as.data.frame(tt)

我有以下代码。它是为&#34; Sta&#34;分配价值。列受特定条件的影响,并在&#34; Nu&#34;中添加差异。在i和i + 1之间进入&#34;滞后&#34;列。

library(dplyr)
# to sort "Na" column and arrange "Nu" in descending order
# in order to apply the code below. 
test2 <- tt %.% arrange(Na, -Nu)
for (i in 1:nrow(test2)) {

  if (i < nrow(test2)) {

    if (test2[i, ]$Nu - 2 > test2[i+1, ]$Nu) {
      test2[i, 4] <- "N"
      test2[i, 5] <- test2[i, ]$Nu - test2[i+1, ]$Nu
    } else if (test2[i, ]$Nu - 2 <= test2[i+1, ]$Nu) {
      test2[i, 4] <- "Y"
      test2[i, 5] <- test2[i, ]$Nu - test2[i+1, ]$Nu
    }

  } else if (i == nrow(test2)) {
    test2[i, 4] <- "N"
    test2[i, 5] <- 0
  }
}
names(test2)[names(test2) == "V4"] <- "Sta"
names(test2)[names(test2) == "V5"] <- "Lag"
test2

运行代码后,它会产生如下结果:

    Nu Na Vo Sta Lag
1  112  A 50   N   4
2  108  A  1   Y   1
3  107  A  1   Y   1
4  106  A  5   Y   2
5  104  A  2   Y   1
6  103  A  2   N   3
7  100  A 60   Y -20
8  120  B 30   N  11
9  109  B  2   Y   1
10 108  B  4   N   8
11 100  B  1   Y  -9
12 109  C 40   N   0

&#34; Sta&#34;下的值列已正确分配但不适用于&#34;滞后&#34;柱。最初的目的是在&#34; Na&#34;中应用基于不同值/级别的代码,即&#34; A&#34;,&#34; B&#34;,&#34; C&# 34 ;.不要将代码应用到&#34; A&#34;,&#34; B&#34;,&#34; C&#34;单独并将单独的结果合并到一个表中。期望的结果应该是:

    Nu Na Vo Sta Lag
1  112  A 50   N   4
2  108  A  1   Y   1
3  107  A  1   Y   1
4  106  A  5   Y   2
5  104  A  2   Y   1
6  103  A  2   N   3
7  100  A 60   Y   0 << Last row for "A". "Lag" should be "0"; "Sta" should be "N".
8  120  B 30   N  11
9  109  B  2   Y   1
10 108  B  4   N   8
11 100  B  1   Y   0 << Last row for "B". "Lag" should be "0"; "Sta" should be "N".
12 109  C 40   N   0 << Last row for "C". "Lag" should be "0"; "Sta" should be "N".

被修改

不确定如何将代码应用于&#34; Na&#34;:&#34; A&#34;,&#34; B&#34;和&#34; C&#34;。可以使用split()或应用函数系列吗?从上面代码的结果和意图可以看出,结果应该是FACTOR / LEVEL / Element依赖(希望我使用正确的术语)并且会影响&#34; Sta&#34;和&#34;滞后&#34;列。但是我的代码无法区分这一点。感谢您提供的任何帮助。感谢

一个不优雅的解决方案!

为了完整起见,我在此发布了一个可能的解决方案。我用硬编码来编码。如果有人可以帮助简化它,那将非常感激。

con <- textConnection('
  Nu Na Vo
 100  A 60
 103  A 2
 104  A 2
 106  A 5
 107  A 1
 108  A 1
 112  A 50
 100  B 1
 108  B 4
 109  B 2
 120  B 30
 109  C 40
                      ')
tt <- read.table(con, header = T)
close(con)
require(dplyr); require(data.table)
test2 <- tt %.% arrange(Na, -Nu)
spl <- split(test2, test2$Na)
spl
for (i in 1:length(levels(test2$Na))) {
  for (j in 1:nrow(spl[[i]])) {

    if (j < nrow(spl[[i]])) {

      if (spl[[i]][j, ]$Nu - 2 > spl[[i]][j+1, ]$Nu) {
        spl[[i]][j, 4] <- "N"
        spl[[i]][j, 5] <- spl[[i]][j, ]$Nu - spl[[i]][j+1, ]$Nu
      } else if (spl[[i]][j, ]$Nu - 2 <= spl[[i]][j+1, ]$Nu) {
        spl[[i]][j, 4] <- "Y"
        spl[[i]][j, 5] <- spl[[i]][j, ]$Nu - spl[[i]][j+1, ]$Nu
      }
    } else if (j == nrow(spl[[i]])) {
      spl[[i]][j, 4] <- "N"
      spl[[i]][j, 5] <- 0
    } 
  }
}
spl <- rbindlist(spl)
setnames(spl, c("V4", "V5"), c("Sta", "Lag"))
spl

1 个答案:

答案 0 :(得分:0)

ave拯救 - 如果应用两次,这将基本上与您的长循环代码进行相同的比较。

首先,使用diff为每个组计算滞后差异,并将每个组中最后一行的值设置为0.然后使用计算的滞后值来确定&#34; Sta&#34;列,强制分配每个组的最后一行&#34; N&#34;。

test2$Lag <- with(test2, ave(Nu,  Na, FUN=function(x) -c(diff(x),0)) )
test2$Sta <- with(test2, ave(Lag, Na, FUN=function(x) {
             out <- ifelse(x > 2, "N", "Y"); out[length(out)] <- "N"; out}))

与要求相同的结果:

test2[c(1:3,5,4)]

#    Nu Na Vo Sta Lag
#1  112  A 50   N   4
#2  108  A  1   Y   1
#3  107  A  1   Y   1
#4  106  A  5   Y   2
#5  104  A  2   Y   1
#6  103  A  2   N   3
#7  100  A 60   N   0
#8  120  B 30   N  11
#9  109  B  2   Y   1
#10 108  B  4   N   8
#11 100  B  1   N   0
#12 109  C 40   N   0