在同一列中调用特定单元格(使用dplyr?)

时间:2018-05-03 00:27:05

标签: r dplyr

我有一个包含字符和数字数据的数据框。我想使用dplyr创建按时间点和试验分组的摘要,生成以下内容:

  1. 平均值
  2. 标准偏差
  3. 变种
  4. 时间点之间的比率

    (等等)

  5. 我觉得所有这些都可以在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),"%"))
    

    但是我仍然坚持在“如何”调用管道内的特定单元格或者使用哪些其他工具/包来计算同一列中单元格之间的增量或比率。

    提前致谢

2 个答案:

答案 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)来创建数据集