我有一个包含字符和数字数据的数据框。我想使用dplyr创建按时间点和试验分组的摘要,生成以下内容:
时间点之间的比率
(等等)
我觉得所有这些都可以在dplyr管道中完成,但我很难在试验中的时间点之间做出平均比率。
我完全承认我可能带着锤子寻找钉子,所以请随意推荐使用其他包装或功能的解决方案,但理想情况下我想要简单/直接的代码,以便多个合作者使用
library(dplyr)
# creating an example DF
num <- runif(100, 50, 3200)
smpl <- 1:100
df <- data.frame( num, smpl)
df$time <- "time1"
df$time[seq(2,100,2)] <- "time2"
df$trial <- "a"
df$trial[26:50] <- "b"
df$trial[51:75] <- "c"
df$trial[75:100] <- "d"
# using the magic of pipelines to calculate useful things
df1 <- df %>%
group_by(time, trial) %>%
summarise(avg = mean(num),
var = var(num),
stdev = sd(num))
我很想获得上面这个区块中包含的 [每次试验的平均时间2 /时间1] ,但我不知道怎么称“avg”专门用“管道内的time1“vs”time2“。
从现在开始,没有什么能达到我所希望的......
df1 <- df1[with(df1,order(trial,time)),]
# this better ressembles my actual DF structure,
# so reordering it will make some of my next attempts to solve this make more sense
我试图使用“每隔一行”不同的事实(这是不理想的,因为每个df将有不同的行数,所以我要么引入NA,要么不断改变这些#(或写一个函数来不断改变它们))
tm2 <- data.frame(x=df1$avg[seq(2,4,2)])
tm1 <- data.frame(x=df1$avg[seq(1,3,2)])
如此微不足道,这是我想要包含在df中的比例,但与平均值和平均值相关联。试用栏:
tm2/tm1
对于我来说这个比率最终排在哪一行并不重要,只要它在所有试验中都是一致的(所以如果一列比率对于每个“时间1”和“值”都是“空白” “对于每个”时间2“,这很好。)
# I added in a separate column to allow 'match' later
tm1$time <- "time1"
tm2$time <- "time1" # to keep them all 'in row'
df1$avg_tm1 <- tm1$x[match(df1$time, tm1$time)]
df1$avg_tm2 <- tm2$x[match(df1$time, tm2$time)]
但是这也无法与'试验'相匹配,因为这个新信息在这个新的tm1 df中丢失了;这真的让我觉得它应该首次在dplry完成...... 然后我尝试在比率为
的tm1 df中创建一个新列tm2$ratio <-tm2$x/tm1$x
并仅在平均值匹配时添加比率值
df1$ratio <- tm2$ratio[match(tm2$x, df1$avg)]
这可能有用,但是当我提取平均值时,它会四舍五入,因此数字不完全匹配。我对此也持谨慎态度,因为如果我处理大量数据,那么两个随机平均值的相似性就会越来越高,以至于错放这些比率。
我尝试了其他一些完全失败的事情,所以让我们假装一些工作并将df1作为单独的列输入比率
然后任何进一步的计算或注释都是直截了当的:
df2 <- df1 %>%
mutate(ratio = avg_tm2/avg_tm1,
lost = 1- ratio,
word = paste0(round(lost*100),"%"))
但是我仍然坚持在“如何”调用管道内的特定单元格或者使用哪些其他工具/包来计算同一列中单元格之间的增量或比率。
提前致谢
答案 0 :(得分:0)
制作单独的data.frame:
set.seed(2)
# your code above to generate df1
df2 <- select(df1, time, trial, avg) %>%
spread(time, avg) %>%
mutate(ratio = time2/time1)
df2
# # A tibble: 4 × 4
# trial time1 time2 ratio
# <chr> <dbl> <dbl> <dbl>
# 1 a 1815.203 1443.731 0.7953555
# 2 b 2012.436 1379.981 0.6857266
# 3 c 1505.474 1641.439 1.0903135
# 4 d 1386.876 1619.341 1.1676176
现在您可以将相关列合并到原始框架上:
left_join(df1, select(df2, trial, ratio), by="trial")
# Source: local data frame [8 x 6]
# Groups: time [?]
# time trial avg var stdev ratio
# <chr> <chr> <dbl> <dbl> <dbl> <dbl>
# 1 time1 a 1815.203 715630.4 845.9494 0.7953555
# 2 time1 b 2012.436 1299823.3 1140.0979 0.6857266
# 3 time1 c 1505.474 878168.3 937.1063 1.0903135
# 4 time1 d 1386.876 902363.7 949.9282 1.1676176
# 5 time2 a 1443.731 998943.3 999.4715 0.7953555
# 6 time2 b 1379.981 720134.6 848.6074 0.6857266
# 7 time2 c 1641.439 1205778.0 1098.0792 1.0903135
# 8 time2 d 1619.341 582417.5 763.1629 1.1676176
答案 1 :(得分:0)
我们可以通过“试用”进行分组。并mutate
创建&#39;比率&#39;柱
df1 %>%
group_by(trial) %>%
mutate(ratio = last(avg)/first(avg))
# A tibble: 8 x 6
# Groups: trial [4]
# time trial avg var stdev ratio
# <chr> <chr> <dbl> <dbl> <dbl> <dbl>
#1 time1 a 1815. 715630. 846. 0.795
#2 time1 b 2012. 1299823. 1140. 0.686
#3 time1 c 1505. 878168. 937. 1.09
#4 time1 d 1387. 902364. 950. 1.17
#5 time2 a 1444. 998943. 999. 0.795
#6 time2 b 1380. 720135. 849. 0.686
#7 time2 c 1641. 1205778. 1098. 1.09
#8 time2 d 1619. 582418. 763. 1.17
注意:我们使用set.seed(2)
来创建数据集