在某些条件下使用for循环

时间:2015-02-05 22:27:33

标签: r

我的数据如下:

ROW ID DV IDV
1   1   0  0.25
2   1  34  0.5  
3   1  33  1
4   1  20  2
5   1  19  3
6   1  18  4
7   1  15  5
8   1  10  6
9   2   0  0.25
10  2  40  0.5  
11  2  39  1
12  2  35  2
13  2  28  3
14  2  20  4
15  2  13  5
16  2   9  6
17  3   0  0.25
18  3  30  0.5  
19  3  20  1
20  3  19  2
21  3  18  3
22  3  17  4
23  3  12  5
24  3   7  6

我希望它看起来像这样:

ROW ID DV IDV    NEWDV
1   1   0  0.25     0
2   1  34  0.5     34
3   1  33  1       33  
4   1  20  2       20
5   1  19  3        9.5
6   1  18  4        4.5
7   1  15  5        1.875
8   1  10  6        0.375
9   2   0  0.25     0
10  2  40  0.5     40
11  2  39  1       39
12  2  35  2       35
13  2  28  3       28
14  2  20  4       20
15  2  13  5        6.5
16  2   9  6        2.25
17  3   0  0.25     0
18  3  30  0.5     30
19  3  20  1       20
20  3  19  2       19
21  3  18  3        9
22  3  17  4        4.25
23  3  12  5        1.5
24  3   7  6        0.4375

我有很多像这样的数据集,我正在尝试为每个数据集完成相同的操作。那么,我想要做的是通过将DV值除以2,4,8,16,24,128等来创建一列NEWDV(即2提升到1,2,3,4,5,6,7和等等)。我想在IDV&gt;时才这样做2和DV <20。例如,取第21至24行,对于这四行的条件 DV&LT; 20和IDV>已经满足2并且NEWDV列读数为18/2 = 9,17 / 4 = 4.25,12 / 8 = 1.5,7 / 16 = 0.4375。必须为每个ID重置此计算。

我尝试使用以下代码但没有成功:

fc是具有数据的对象

x <- c(2,4,8,16)
for(i in 1:4){
    for(j in 1:4){
        for(g in 1:length(fc$DV<20 & fc$ID==i & fc$IDV>2)) {
            fc$NEWDV[g] <-ifelse(fc$DV[fc$ID==i][g]<20 & fc$IDV[fc$ID==i][g]>2,fc$DV[fc$ID==i][g]/x[j],fc$DV[fc$ID==j][g])
        }
    }
}

我做错了什么?非常感谢帮助!!我想只为这个问题使用for循环。还欢迎任何其他解决方案。我只是熟悉for循环。谢谢。

2 个答案:

答案 0 :(得分:3)

现在是时候使用cumsum函数计算行数(包括当前行,其中条件(IDV&gt; 2和DV&lt; 20)为真)的行数;你可以将DV标准化为两个上升到这个累积和的幂。然后,您可以将此功能应用于按ID分解的数据框的每个部分。

# Split by ID
spl <- split(dat, dat$ID)

# Grab the normalized DV value for each grouping
new.dv <- lapply(spl, function(x) x$DV / 2^cumsum(x$IDV > 2 & x$DV < 20))

# Add the new values back to your data frame
dat$NEWDV <- unlist(new.dv)
dat
#    ROW ID DV  IDV   NEWDV
# 1    1  1  0 0.25  0.0000
# 2    2  1 34 0.50 34.0000
# 3    3  1 33 1.00 33.0000
# 4    4  1 20 2.00 20.0000
# 5    5  1 19 3.00  9.5000
# 6    6  1 18 4.00  4.5000
# 7    7  1 15 5.00  1.8750
# 8    8  1 10 6.00  0.6250
# 9    9  2  0 0.25  0.0000
# 10  10  2 40 0.50 40.0000
# 11  11  2 39 1.00 39.0000
# 12  12  2 35 2.00 35.0000
# 13  13  2 28 3.00 28.0000
# 14  14  2 20 4.00 20.0000
# 15  15  2 13 5.00  6.5000
# 16  16  2  9 6.00  2.2500
# 17  17  3  0 0.25  0.0000
# 18  18  3 30 0.50 30.0000
# 19  19  3 20 1.00 20.0000
# 20  20  3 19 2.00 19.0000
# 21  21  3 18 3.00  9.0000
# 22  22  3 17 4.00  4.2500
# 23  23  3 12 5.00  1.5000
# 24  24  3  7 6.00  0.4375

这种分解数据框架,应用某种功能以及将结果组合在一起的方法称为split-apply-combine,是一种常见的数据争用方法。

答案 1 :(得分:1)

在这里,我们使用data.table。转换&#34; data.frame&#34;到&#34; data.table&#34; (setDT(df))。创建新列(&#34; NEWDV&#34;将&#34; DV&#34;类转换为&#34;数字&#34 ;;逻辑&#34; indx&#34;列)。分配(:=)&#34; NEWDV&#34;更改值(NEWDV/2^...)当&#34; indx&#34;在按&#34; ID&#34;分组后,为TRUE((indx))。删除&#34; indx&#34;列通过将其分配给&#34; NULL&#34;

library(data.table)
setDT(df)[,c('NEWDV', 'indx'):= list(as.numeric(DV),
    IDV>2 & DV <20)][(indx), NEWDV:=NEWDV/2^cumsum(indx), ID][,indx:=NULL][]
#     ROW ID DV  IDV   NEWDV
#  1:   1  1  0 0.25  0.0000
#  2:   2  1 34 0.50 34.0000
#  3:   3  1 33 1.00 33.0000
#  4:   4  1 20 2.00 20.0000
#  5:   5  1 19 3.00  9.5000
#  6:   6  1 18 4.00  4.5000
#  7:   7  1 15 5.00  1.8750
#  8:   8  1 10 6.00  0.6250
#  9:   9  2  0 0.25  0.0000
# 10:  10  2 40 0.50 40.0000
# 11:  11  2 39 1.00 39.0000
# 12:  12  2 35 2.00 35.0000
# 13:  13  2 28 3.00 28.0000
# 14:  14  2 20 4.00 20.0000
# 15:  15  2 13 5.00  6.5000
# 16:  16  2  9 6.00  2.2500
# 17:  17  3  0 0.25  0.0000
# 18:  18  3 30 0.50 30.0000
# 19:  19  3 20 1.00 20.0000
# 20:  20  3 19 2.00 19.0000
# 21:  21  3 18 3.00  9.0000
# 22:  22  3 17 4.00  4.2500
# 23:  23  3 12 5.00  1.5000
# 24:  24  3  7 6.00  0.4375

数据

df <- structure(list(ROW = 1:24, ID = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 
3L), DV = c(0L, 34L, 33L, 20L, 19L, 18L, 15L, 10L, 0L, 40L, 39L, 
35L, 28L, 20L, 13L, 9L, 0L, 30L, 20L, 19L, 18L, 17L, 12L, 7L), 
IDV = c(0.25, 0.5, 1, 2, 3, 4, 5, 6, 0.25, 0.5, 1, 2, 3, 
4, 5, 6, 0.25, 0.5, 1, 2, 3, 4, 5, 6)), .Names = c("ROW", 
"ID", "DV", "IDV"), class = "data.frame", row.names = c(NA, -24L))