2016-12-29 52 views
3

dput(list[200:250,])避免for循環時,需要預留計算R中每個子集

structure(list(id = c(10L, 10L, 10L, 10L, 10L, 10L, 12L, 12L, 
12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 
12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 14L, 14L, 14L, 
14L, 14L, 14L, 14L, 14L, 14L, 14L, 14L, 14L, 14L, 14L, 14L, 14L, 
14L, 14L, 14L, 14L), group = c(3, 3, 3, 3, 3, 3, 2, 2, 1, 3, 
3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 3, 3, 
2, 2, 2, 3, 1, 3, 2, 2, 3, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 2)), .Names = c("id", 
"group"), row.names = c(3618L, 3218L, 3372L, 3613L, 3217L, 3531L, 
3653L, 3835L, 3748L, 3740L, 4007L, 3769L, 3915L, 3834L, 3813L, 
3927L, 4066L, 4048L, 3978L, 3731L, 4030L, 3721L, 3869L, 4070L, 
4021L, 3789L, 3749L, 3739L, 3964L, 3924L, 4023L, 4284L, 4238L, 
4102L, 4642L, 4309L, 4577L, 4784L, 4125L, 4346L, 4088L, 4406L, 
4785L, 4893L, 4347L, 4498L, 4758L, 4686L, 4469L, 4864L, 4193L 
), class = "data.frame") 

我的代碼:

for (i in 1:(max(list$id))) { 
    p <- subset(list,list$id==i) 
    h <-0 
    for (j in 1:(nrow(p)-1)){ 
    if (p$group[j]!=p$group[(j+1)]) { 
     h <- (h+1) 
     } 
    } 
    list$group_move[list$id==i] <- h 
} 

錯誤:

Error in if (p$group[j] != p$group[(j + 1)]) { : 
    missing value where TRUE/FALSE needed 
  • 我檢查N/A( is.na(list))並且是錯誤的。

我的列表:

我有5000分號的,我可以有 「34526」 作爲ID。 我需要爲每個不同的id計算他們在組1,2和3之間移動的次數。 我知道2「for」效率不高,但我不知道區分每個id的不同方法。

如果你能幫我理解我的代碼有什麼問題這將是很棒的。 如果你知道寫一種方式來表彰每一個不同的id,它會更好(這個表示不是常規函數)。

+1

您的示例數據在「組」之間沒有移動。請提供一個最小可重現的例子。 – MichaelChirico

+0

@ MichaelChirico在Q. – anat

回答

1

使用dplyr和調用數據dd

library(dplyr) 
dd %>% 
    group_by(id) %>% 
    summarize(changes = sum(lag(group) != group, na.rm = T)) 
# # A tibble: 3 × 2 
#  id changes 
# <int> <int> 
# 1 10  0 
# 2 12  7 
# 3 14  8 

以上總結爲每組動作的次數。爲了代替此列添加到原始數據幀,我們與mutate替換summarize

dd2 = dd %>% 
    group_by(id) %>% 
    mutate(group_move = sum(lag(group) != group, na.rm = T)) 
dd2 
# Source: local data frame [51 x 3] 
# Groups: id [3] 
# 
#  id group group_move 
# <int> <dbl>  <int> 
# 1  10  3   0 
# 2  10  3   0 
# 3  10  3   0 
# 4  10  3   0 
# 5  10  3   0 
# 6  10  3   0 
# 7  12  2   7 
# 8  12  2   7 
# 9  12  1   7 
# 10 12  3   7 
# # ... with 41 more rows 

我覺得你的代碼的唯一問題是,它可以擊中不存在id值。這會導致空子集和缺少的條件錯誤。一個簡單的解決方法是用for (i in unique(list$id))更換for (i in 1:(max(list$id)))

list = dd 

for (i in unique(list$id)) { 
    p <- subset(list,list$id==i) 
    h <-0 
    for (j in 1:(nrow(p)-1)){ 
    if (p$group[j] != p$group[(j+1)]) { 
     h <- (h+1) 
    } 
    } 
    list$group_move[list$id==i] <- h 
} 

這工作,但會比dplyr版本慢得多。我們可以用矢量代替內環加速這一過程:

for (i in unique(list$id)) { 
    p <- subset(list,list$id==i) 
    h <- sum(p$group[-1] != p$group[-nrow(p)]) 
    list$group_move[list$id==i] <- h 
} 

實際上,這就是我們做了與dplyr頂部 - 的lag()是一個方便的功能,以抵消指數,以及group_by()需要的護理分開處理每個id

+0

中更改它非常感謝。 – anat

+0

如果我想計算每個ID的標準偏差和斜率,我該怎麼做?這可以嗎? h'<- list %>%group_by(id)%>%summarize(new_list = sd(value),na.rm = T) – anat

+0

幾乎想要'na.rm = T'成爲'sd()'的參數而不是'總結()'。 – Gregor