簡體   English   中英

如何在data.frame中創建表示特定列的均值的列?

[英]How do I create a column of means of specific columns in a data.frame?

感謝您的答復和回答。 我可以看到我無意中遺漏了一些重要的細節,可以幫助您更好地理解我的問題。 我試圖使它簡單和通用,但這實際上沒有幫助。 這是具有更多信息的更新版本。

我有一個data.frame ,其中有許多列來自BehaviorSpace生成的NetLogo模型。 每列都是一個時間序列,表示在不同實驗條件下的報告值,重復次數由運行編號和時間步長編號表示。 例如(很抱歉,這個時間很長,但是我想為您介紹一下數據):

# Start by building a fake data.frame that models some of the characteristics of mine:
df <- data.frame(run = c(rep(1,5), rep(2,5), rep(3,5), rep(4,5), rep(5,5), rep(6,5), rep(7,5), rep(8,5)))
df2 <- expand.grid(step = 1:5, fac.a = c(10,1000), fac.b = c(0.5,2.0))
df <- data.frame(run = df$run, rep = c(rep(1,20), rep(2,20)), step = df2$step, fac.a = df2$fac.a, fac.b = df2$fac.b)
log_growth <- function (a, b, x) {(1/(1+a*exp(-b*x))) + rnorm(1,0,0.2)}
set.seed(11)
df$treatment1 <- log_growth(df$fac.a, df$fac.b, df$step)
df$treatment2 <- log_growth(df$fac.a / 2, df$fac.b * 2, df$step)

這會將以下內容放入df中:

> df
   run rep step fac.a fac.b  treatment1  treatment2
1    1   1    1    10   0.5  0.05288201 0.356176584
2    1   1    2    10   0.5  0.12507561 0.600407158
3    1   1    3    10   0.5  0.22081815 0.804671117
4    1   1    4    10   0.5  0.33627099 0.920093934
5    1   1    5    10   0.5  0.46053940 0.971397427
6    2   1    1  1000   0.5 -0.08700866 0.009396323
7    2   1    2  1000   0.5 -0.08594375 0.018552055
8    2   1    3  1000   0.5 -0.08419297 0.042608835
9    2   1    4  1000   0.5 -0.08131981 0.102435481
10   2   1    5  1000   0.5 -0.07661880 0.232875872
11   3   1    1    10   2.0  0.33627099 0.920093934
12   3   1    2    10   2.0  0.75654214 1.002314651
13   3   1    3    10   2.0  0.88715737 1.003958435
14   3   1    4    10   2.0  0.90800192 1.003988593
15   3   1    5    10   2.0  0.91089154 1.003989145
16   4   1    1  1000   2.0 -0.08131981 0.102435481
17   4   1    2  1000   2.0 -0.03688314 0.860350536
18   4   1    3  1000   2.0  0.19880473 1.000926458
19   4   1    4  1000   2.0  0.66014952 1.003932891
20   4   1    5  1000   2.0  0.86791705 1.003988125
21   5   2    1    10   0.5  0.05288201 0.356176584
22   5   2    2    10   0.5  0.12507561 0.600407158
23   5   2    3    10   0.5  0.22081815 0.804671117
24   5   2    4    10   0.5  0.33627099 0.920093934
25   5   2    5    10   0.5  0.46053940 0.971397427
26   6   2    1  1000   0.5 -0.08700866 0.009396323
27   6   2    2  1000   0.5 -0.08594375 0.018552055
28   6   2    3  1000   0.5 -0.08419297 0.042608835
29   6   2    4  1000   0.5 -0.08131981 0.102435481
30   6   2    5  1000   0.5 -0.07661880 0.232875872
31   7   2    1    10   2.0  0.33627099 0.920093934
32   7   2    2    10   2.0  0.75654214 1.002314651
33   7   2    3    10   2.0  0.88715737 1.003958435
34   7   2    4    10   2.0  0.90800192 1.003988593
35   7   2    5    10   2.0  0.91089154 1.003989145
36   8   2    1  1000   2.0 -0.08131981 0.102435481
37   8   2    2  1000   2.0 -0.03688314 0.860350536
38   8   2    3  1000   2.0  0.19880473 1.000926458
39   8   2    4  1000   2.0  0.66014952 1.003932891
40   8   2    5  1000   2.0  0.86791705 1.003988125

因此,我之前所做的是使用by拆分數據幀by並希望獲得每個步驟(這是一個時間序列)和每個因子組合的平均值和標准差。

在查看了所有答案並重新考慮了我的問題之后,我認為在by的轉換過程中可以更好地處理我要嘗試執行的操作。 我不確定該怎么做...我希望輸出看起來像是一個摘要:

> df
   run fac.a fac.b  mean.treatment1  mean.treatment2 sd.treatment1 sd.treatment2
1    1    10   0.5        xxxxxxxxx       xxxxxxxxxx    xxxxxxxxxx   xxxxxxxxxxx
1    1    10   2.0        xxxxxxxxx       xxxxxxxxxx    xxxxxxxxxx   xxxxxxxxxxx
1    1  1000   0.5        xxxxxxxxx       xxxxxxxxxx    xxxxxxxxxx   xxxxxxxxxxx
1    1  1000   2.0        xxxxxxxxx       xxxxxxxxxx    xxxxxxxxxx   xxxxxxxxxxx

這是aggregate的工作嗎? 感謝您的耐心配合和幫助。 -格倫


原始問題:

我有一個包含許多列的data.frame ,每列代表一個具有重復的特定實驗條件。

> df <- data.frame(a.1 = runif(5), b.1 = runif(5), a.2 = runif(5), b.2 = runif(5), mean.a = 0, mean.b = 0, mean.1 = 0, mean.2 = 0)
> df
        a.1       b.1       a.2       b.2 mean.a mean.b   sd.a   sd.b
1 0.9209433 0.3501444 0.3893140 0.3264827      0      0      0      0
2 0.4171254 0.4883140 0.8282384 0.1215129      0      0      0      0
3 0.2291582 0.9419946 0.4089008 0.5665242      0      0      0      0
4 0.3807868 0.1889066 0.8271075 0.4022014      0      0      0      0
5 0.5863078 0.4991847 0.4082745 0.5637367      0      0      0      0

我想找到每種條件和重復的均值和標准差。 到目前為止,最直接的方法似乎是:

for (i in c("a.1", "a.2") {df$mean.a <- df$mean.a + df[[i]]}
df$mean.a <- df$mean.a / 2

但是我有很多專欄,而且到處都是,所以這看起來真的很耗費人工。 更好的方法是使用ave()

df$mean.a <- with (df, ave(a.1, a.2))

但是,如果我想做sd(),我會神秘地得到NA:

df$sd.a <- with (df, ave(a.1, a.2, FUN = sd))
> df
        a.1       b.1       a.2       b.2    mean.a mean.b   sd.a   sd.b
1 0.9209433 0.3501444 0.3893140 0.3264827 0.9209433      0     NA      0
2 0.4171254 0.4883140 0.8282384 0.1215129 0.4171254      0     NA      0
3 0.2291582 0.9419946 0.4089008 0.5665242 0.2291582      0     NA      0
4 0.3807868 0.1889066 0.8271075 0.4022014 0.3807868      0     NA      0
5 0.5863078 0.4991847 0.4082745 0.5637367 0.5863078      0     NA      0

如果可能的話,我寧願不要使用外部軟件包,但是似乎我缺少一些基本的東西。 這個問題是相似的,但是與data.tables有關,而不與data.frames有關。

另一個甚至更接近,但是使用ave()來指定列1-12、15-17和26作為主題列也很繁瑣,而sd()神秘地產生了這些NA。 似乎應該有一種簡單的方法來執行此操作。 幾乎讓我希望得到Excel。 :-)

讓我們首先將您的數據轉換為可接受的格式。 請注意,此解決方案確實違反了您的最初要求,確實依賴於外部庫,但是今天它們是非常普遍且真正的節省時間! (Ryr社區中的一種現象Hadley Wickham撰寫的plyr and reshape2)

# Note how I only used the data columns, initially, there is no mean and sd column in the data frame used at this stage.
df <- data.frame(a.1 = runif(5), b.1 = runif(5), a.2 = runif(5), b.2 = runif(5))

df$repetition = c(1:nrow(df))
library(reshape2)
tmp = melt(df, id.vars = "repetition")
names(tmp)[2] = "condition"

tmp$treatment = substring(tmp$condition,1,1)

這樣產生:

> head(tmp)
  repetition condition     value treatment
1          1       a.1 0.6668952         a
2          2       a.1 0.1248151         a
3          3       a.1 0.7082199         a
4          4       a.1 0.9840956         a
5          5       a.1 0.4479190         a
6          1       b.1 0.9381539         b

現在,剩下的事情很容易了,我們依靠流行的plyr軟件包:

library(plyr)
results = ddply(tmp, .(repetition, treatment), summarize, mean = mean(value), sd = sd(value) )

最終結果是

> head(results)
  repetition treatment      mean         sd
1          1         a 0.6777342 0.01532853
2          1         b 0.6734955 0.37428353
3          2         a 0.4533126 0.46456561
4          2         b 0.8441925 0.07260509
5          3         a 0.3967338 0.44050779
6          3         b 0.5886821 0.42635902

希望這就是您想要的。

如果您不想區分每個重復,而是在治療水平上,則還有一個更有趣的補充

# addition
results = ddply(tmp, .( treatment), summarize, mean = mean(value), sd = sd(value) )

結果:

> head(results)
  treatment      mean        sd
1         a 0.5817867 0.2954151
2         b 0.6212537 0.3219035

使用tidyrtidyr的管道運算符, magrittr將數據鞭打成形狀的“僅基礎”要求:

set.seed(42)
df  <- data.frame(a.1 = runif(5), b.1 = runif(5), a.2 = runif(5), b.2 = runif(5))
df2 <- df %>%
  gather(treatment, value) %>%
  separate(treatment, c("treatment", "repetition"))
head(df2)
#    treatment repetition      value
# 1          a          1 0.13871017
# 2          a          1 0.98889173
# 3          a          1 0.94666823
# 4          a          1 0.08243756
# 5          a          1 0.51421178
# 6          b          1 0.39020347

現在,我不確定您要獲取的平均值和標准偏差到底是什么,但是一個簡單的選擇是從基數R的aggregate() 。簡單地通過FUN參數傳遞所需的函數:

# calculate mean on treatment (a or b)
aggregate(df2$value, by = list(treatment = df2$treatment), FUN = mean)
#   treatment repetition         x
# 1         a          1 0.5341839
# 2         b          1 0.6633022
# 3         a          2 0.5442395
# 4         b          2 0.4225865

# calculate mean on treatment and repetition
aggregate(df2$value, by = list(treatment = df2$treatment, repetition = df2$repetition, FUN = mean)
#   treatment         x
# 1         a 0.5392117
# 2         b 0.5429444

根據您顯示的代碼,這種base R方法可能會有所幫助:

 set.seed(42)
 df <- data.frame(a.1 = runif(5), b.1 = runif(5), a.2 = runif(5), b.2 = runif(5))
   do.call(cbind,
     lapply(split(seq_along(df),gsub("\\..*", "",colnames(df))), function(x) {
        x1 <- df[,x]
        data.frame(Means=rowMeans(x1, na.rm=TRUE), SD=apply(x1, 1, sd, na.rm=TRUE))}))
  #  a.Means      a.SD   b.Means       b.SD
  #1 0.6862739 0.3231932 0.7295552 0.29763438
  #2 0.8280938 0.1541232 0.8574074 0.17086395
  #3 0.6104059 0.4585819 0.1260770 0.01214755
  #4 0.5429382 0.4065997 0.5659947 0.12869005
  #5 0.5520192 0.1268922 0.6326988 0.10234101

使用您的代碼,我得到相同的結果

  vec1 <- vector("numeric", length=5)
  for(i in c("a.1", "a.2")) {vec1 <- vec1+df[[i]]}
  vec1/2
  #[1] 0.6862739 0.8280938 0.6104059 0.5429382 0.5520192

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM