Как применить целый скрипт со многими вычислениями к каждому столбцу в data.frame - PullRequest
0 голосов
/ 26 апреля 2019

Мне нужно применить ряд вычислений к одному столбцу во фрейме данных.Для этого я извлекаю столбец, создаю новый фрейм данных, а затем начинаю строить его с новыми столбцами, которые содержат в основном простые вычисления. Затем мне нужно повторить этот (довольно длинный скрипт) для каждого столбца во фрейме данных.

Применить семейство не работает, потому что мне не удается объединить все свои вычисления в одну функцию (x)

Мой исходный фрейм данных выглядит следующим образом, гдеS - это номера участков, а значения - биомасса (годы 1981: 2007 и сайты S1: S25).Я хочу, чтобы приведенный ниже скрипт был применен к каждому отдельному столбцу (каждому сайту) и отдельному кадру выходных данных на столбец.

мой data.frame называется ts.bio, он включает в себя NA

    year S1 S2 S3  S4  S5  S6  S7 S8  S9 S10 S11 S12 S13 S14 S15
    1981 94 91 92 103 162 104 125 91 108 101 117 138 115  95  99
    1982 33 52 52  73 109  40  41 55  51  77  77 100  54  44  62
    1983 26 14 30  29  46  14  16 25  11  24  31  31  19  11  28

Это сценарий, который мне нужно применить к каждому столбцу

    change<-NULL

    for (i in 1881:2007){
      lambda<-tsBio$S1[tsBio$year==i+1]/tsBio$S1[tsBio$year==i]
      change<-c(change, lambda)
         }


    print(change)

    #edit the data frame 
    change<-as.data.frame(change)  
    change$t<-c(1:26)    #add time 
    change$year<-c(1982:2007)   #add year 

    # I need DataCombine for the Insert Row line 
    library("DataCombine")
    NewRow<-c(0, 0, 1981)   #create new row
    change<-InsertRow(change, NewRow, RowNum=1) #ad new row

    change$biomass<- tsBio$S1   #add population size


    #create a lagged version to compute delta for differentiated B      (B')
    change$changelag<-change$change #duplicate column
    change$biomasslag<-change$biomass #duplicate column 
    change$tlag<-change$t


    #before this I need to detach dataCombine and activate data.table
    detach("package:DataCombine", unload=TRUE)
    library("data.table")
    change$changelag<-shift(change$changelag, n=1, type="lag")
    change$biomasslag<-shift(change$biomasslag, n=1, type="lag")
    change$tlag<-shift(change$tlag, n=1, type="lag")


    #compute nominator and denominator of differentiated B (B')
    change$deltaB<-(change$change-change$changelag)
    change$deltaX<- (change$biomass - change$biomasslag)

    change$Bdiff<-(change$deltaB/change$deltaX) 

    #compute mortality differentiated
    change$deltat<-(change$t-change$tlag)
    change$M<- change$change-(change$deltaX/change$deltat)

    change$Mdiff<-(change$M/change$biomass)

    change$lambda<-(change$Bdiff-change$Mdiff)

    library("ggplot2")
     ggplot(data=change, aes(x=year))+
     geom_point(aes(y=lambda))

Я пытался использовать циклы и применять семейство, но не смог ничего сделать.Создание одной функции (function (x)) для «lapply» кажется безумным, потому что в скрипте так много контента.

Спасибо, см за предложения!И извините за глупость.

1 Ответ

0 голосов
/ 26 апреля 2019

Я бы предложил реструктурировать ваши данные из широкого в длинный формат, а затем использовать dplyr.В этом случае каждая строка будет для наблюдения и будет иметь столбец для года, места №, лямбда, биомассы и т. Д., И она будет хранить все ваши данные в одном удобном фрейме данных.Получение данных для определенных сайтов, лет и т. Д. С помощью filter легко.Вот пример:

# Create dummy data frame
df <- data.frame(year = 1981:2007,
                 t = 1:27,
                 S1 = sample(1:200, 27, replace = TRUE),
                 S2 = sample(1:200, 27, replace = TRUE),
                 S3 = sample(1:200, 27, replace = TRUE),
                 S4 = sample(1:200, 27, replace = TRUE),
                 S5 = sample(1:200, 27, replace = TRUE))

# Quick peak
head(df)
#>   year t  S1  S2  S3  S4  S5
#> 1 1981 1 163 133  86  59  40
#> 2 1982 2  99  28 190 179  58
#> 3 1983 3  94 136   6  47 185
#> 4 1984 4 199  87 137  31  20
#> 5 1985 5 157 169 172  24  21
#> 6 1986 6 105  33 189 122 148

Это структура ваших исходных данных в широком формате.Давайте изменим его на длинный формат и проведем некоторые вычисления.

# Load libraries
library(dplyr)
library(magrittr)
library(tidyr)


# 1) Convert to long format
# 2) Group by site for calculations
# 3) Calculate lambda, change in biomass
# 4) Ungroup
df %<>% 
  gather(site, biomass, S1:S5) %>% 
  group_by(site) %>% 
  mutate(lambda = biomass/lag(biomass),
         delta_biomass = biomass - lag(biomass)) %>% 
  ungroup

# Quick peak
head(df)
# # A tibble: 6 x 6
#    year     t site  biomass  lambda delta_biomass
#   <int> <int> <chr>   <int>   <dbl>         <int>
# 1  1981     1 S1        175 NA                 NA
# 2  1982     2 S1         74  0.423           -101
# 3  1983     3 S1        177  2.39             103
# 4  1984     4 S1         15  0.0847          -162
# 5  1985     5 S1         28  1.87              13
# 6  1986     6 S1        150  5.36             122

Теперь ваши данные представлены в длинном формате, и мы провели некоторые вычисления, используя mutate, который просто добавляет несколько столбцов в ваш фрейм данных.(Он также может перезаписывать столбцы.) Обратите внимание, что мне не нужно было создавать промежуточные столбцы с задержками в моих вычислениях, я просто использовал lag.Таким образом, вы можете добавлять все свои вычисления без каких-либо циклов, и это обеспечивает чистый, читаемый код.Кроме того, реструктуризация данных, подобная этой, означает, что вам не нужно делать это для каждого столбца сайта, так как он применяется ко всем одновременно.

Сначала все эти данные могут показаться обременительнымивместе в одном месте, но на самом деле очень просто извлечь нужные данные, используя filter.Например:

# Only see data for site S4 between 2000 and 2005
df %>% 
  filter(site == "S4", 
         between(year, 2000, 2005))
# # A tibble: 6 x 6
#     year     t site  biomass lambda delta_biomass
#    <int> <int> <chr>   <int>  <dbl>         <int>
# 1  2000    20 S4        124  1.38             34
# 2  2001    21 S4        116  0.935            -8
# 3  2002    22 S4        178  1.53             62
# 4  2003    23 S4         92  0.517           -86
# 5  2004    24 S4        107  1.16             15
# 6  2005    25 S4         87  0.813           -20

Редактировать

Я пропустил группировку сайтов в исходной версии, которая теперь исправляется.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...