在dplyr中比较分组内一列的值

3
我希望能够使用dplyr比较分组数据框内的值,并创建一个哑变量或类似的东西,指示哪个更大。但我无法想出解决方法!
以下是一些可重现的代码:
table <- structure(list(species = structure(c(1L, 1L, 1L, 2L, 2L, 2L), .Label = c("Adelophryne adiastola", 
"Adelophryne gutturosa"), class = "factor"), scenario = structure(c(3L, 
1L, 2L, 3L, 1L, 2L), .Label = c("future1", "future2", "present"
), class = "factor"), amount = c(5L, 3L, 2L, 50L, 60L, 40L)), .Names = c("species", 
"scenario", "amount"), class = "data.frame", row.names = c(NA, 
-6L))
> table
                species scenario amount
1 Adelophryne adiastola  present      5
2 Adelophryne adiastola  future1      3
3 Adelophryne adiastola  future2      2
4 Adelophryne gutturosa  present     50
5 Adelophryne gutturosa  future1     60
6 Adelophryne gutturosa  future2     40

我会将df按照species分组。 我想创建一个新的列,可以是increase_amount,其中每个“未来”中的数量与“现在”进行比较。当数值增加时,我可以得到1,而当它减少时,我可以得到0。
我一直在尝试使用for循环遍历每个物种,但是df包含超过50,000个物种,对于我需要重新执行操作的时间来说太长了...
有人知道方法吗? 非常感谢!
3个回答

5
你可以这样做:
table %>% 
  group_by(species) %>% 
  mutate(tmp = amount[scenario == "present"]) %>% 
  mutate(increase_amount = ifelse(amount > tmp, 1, 0))
# Source: local data frame [6 x 5]
# Groups: species [2]
# 
#                 species scenario amount   tmp increase_amount
#                  <fctr>   <fctr>   <int> <int>           <dbl>
# 1 Adelophryne adiastola  present      5     5               0
# 2 Adelophryne adiastola  future1      3     5               0
# 3 Adelophryne adiastola  future2      2     5               0
# 4 Adelophryne gutturosa  present     50    50               0
# 5 Adelophryne gutturosa  future1     60    50               1
# 6 Adelophryne gutturosa  future2     40    50               0

0
似乎你可以使用lag()函数来快速找到随时间变化的差异。建议重组scenario(时间)变量,以便可以使用R函数直观地重新排序(例如,arrange()函数可以按字母顺序重新排序scenario变量,如future1、future2、present,但在这种情况下行不通)。
df <- data.frame(species=rep(letters,3),
                 scenario=rep(1:3,26),
                 amount=runif(78))
summary(df)
glimpse(df)
df %>% count(species,scenario)

df %>% 
  arrange(species,scenario) %>% # arrange scenario by ascending order
  group_by(species) %>% 
  mutate(diff1=amount-lag(amount), # calculate difference from time 1 -> 2, and time 2 -> 3
         diff2=amount-lag(amount,2)) # calculate difference from time 1 -> 3

lag() 的输出将导致每个分组中的前 scenario 个值为 NA,但可以使用 ifelse() 语句或 filter() 轻松更改结果。

df %>% 
  arrange(species,scenario) %>% group_by(species) %>% 
  mutate(diff1=amount-lag(amount)) %>% 
  filter(diff1>0)

df %>% 
  arrange(species,scenario) %>% group_by(species) %>% 
  mutate(diff1=amount-lag(amount)) %>% 
  mutate(diff.incr=ifelse(diff1>0,'increase','no increase'))

0
我们可以使用来自基本R的 ave 来实现这一点。
table$increase_amount <-  with(table, as.integer(amount > ave(amount * 
         (scenario == "present"), species, FUN = function(x) x[x!=0])))
table$increase_amount
#[1] 0 0 0 0 1 0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接