Вызов определенных ячеек в одном и том же столбце (используя dplyr?) - PullRequest
0 голосов
/ 03 мая 2018

У меня есть датафрейм с символьными и числовыми данными. Я хотел бы использовать dplyr для создания сводки, сгруппированной по временным точкам и испытаниям, генерирующей следующее:

  1. средние
  2. Стандартные отклонения
  3. вариант
  4. соотношение между временными точками

    (и т. Д.)

Я чувствую, что все это можно сделать в трубе 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" по времени1 "против" 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, но привязанное к столбцам avg и trial:

tm2/tm1

Для меня не имеет значения, в каком временном ряду заканчивается это соотношение, при условии, что оно согласовано во всех испытаниях (поэтому, если в столбце соотношений есть «пусто» для каждого «времени1» и «значения» "для каждого" time2 ", это нормально).

# 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 голосов
/ 03 мая 2018

Мы могли бы сгруппировать по «триалу» и mutate, чтобы создать столбец «коэффициента»

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) для создания набора данных

0 голосов
/ 03 мая 2018

Разработка отдельного 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...