2013-06-20 47 views
0

這是一個基於我之前問過的問題的問題:Read many files, compute something, save results in dataframe (R)R:構建嵌套for循環和保存結果的問題

我仍然有大約100個文件與模擬數據。主題是兩種物質的降解,所以我有3個相關的列:時間(分鐘),物質1的相對濃度(Sub1,從1.0到零)和相對濃度。物質2(Sub2)。

這工作得很好,以確定某些降解的水平,這是我必須手動輸入:

z <- 0.25 #Abbaugrad 
a <- 1-z 

setwd("H:/...") 
names<-dir(pattern="Data.txt") 
result <- data.frame(matchs1 = numeric(length(names)) , matchs2 = numeric(length(names))) 
for (i in 1:length(names)){ 
    data <- read.table(file=names[i],header=T) 
    matchs1 <- with(data, Time[abs(Sub1-a)==min(abs(Sub1-a))]) 
    matchs2 <- with(data , Time[abs(Sub2-a)==min(abs(Sub2-a))]) 
    result[i,] <- cbind(matchs1,matchs2) 
    } 

現在我想的過程自動化,所以我沒有進入降解水平,但結果在計算一個嵌套的for-loop。

首先,我認爲未來的想法可能會更好地與數據主義者, G。密謀從這個文件的一些數據,所以我所做的:

filelist <- list.files(pattern = "Data.txt") 
datalist <- lapply(filelist, function(xx)read.table(xx,header=T)) 

這工作得很好,從模擬繪製一些運行。

plot(datalist[[1]][,3], type="l",col="red") 
for (i in 1:10){ 
    lines(datalist[[i]][,3],col="red") 
    } 

的原因試圖建構下面的循環是,我想找出跑出100.我想我必須找出當1%到100%被降解爲每個時間的平均值運行,然後計算每個級別的平均值。現在

我簡單的嘗試只是一種物質:

test <- data.frame(matrix(ncol=99, nrow = 100)) #100 runs, 99 levels 
for (i in 1:length(datalist)){ 
    for (j in seq(0.01,0.99,by=0.01)){ 
    matchs1 <- with(datalist[[i]], Time[abs(Sub1-j)==min(abs(Sub1-j))]) 
    level <- paste('l',j,sep="") 
    test[j,] <- cbind(matchs1,level) 
    }} 

我想建立一個新的數據幀,其中每個級別(0.01:1),結果被保存在單個列。然後,我可以計算出每個顏色的均值,然後再計算它。但是我已經無法計算數據幀。

也許還有一種更簡單的方法來獲得不同時間序列的均值。

我真的很感激任何幫助。

編輯: 我很難提供樣本數據,因爲我有100個文件。在他們每一箇中有三個相關的列:Time,Sub1,Sub2。你可以把它想象這樣的:

Time Sub1 Sub2 
0  1.0000 1.0000 
60  0.9511 0.9888 
120  0.9022 0.9555 
... 
24000 0.0101 0.0891 

我想計算的平均運行,因此每個一百文件我算算時間,當0.01,0.02,0.03 ... 0.97,0.98,0.99退化。然後我想計算我的平均值。即所有時間,其中0.01退化。相同的爲0.02,0.03等。最後,我應該有99次升序。

是否可以附加文件?我發現沒有選擇這樣做。

編輯2:

dput的輸出爲所獲得的數據列表由

names <- dir(pattern="Data.txt") 
datalist <- lapply(names, read.table, header=TRUE) 

是:

> dput(head(datalist[[1]])) 
structure(list(Time = c(0L, 60L, 120L, 180L, 240L, 300L), Sub0_Abs = c(1.49899, 
1.49568, 1.49544, 1.49533, 1.49521, 1.49507), Sub0_Rel = c(1, 
0.9978, 0.9976, 0.9976, 0.9975, 0.9974), Sub1_Abs = c(1.49899, 
1.49899, 1.49899, 1.49899, 1.49899, 1.49899), Sub1_Rel = c(1, 
1, 1, 1, 1, 1), TP = c(0.15, 0.1579, 0.1584, 0.1586, 0.1589, 
0.1592), TA = c(0.13, 0.16, 0.18, 0.18, 0.18, 0.22), Sub_Inflow = c(0, 
0, 0, 0, 0, 0)), .Names = c("Time", "Sub0_Abs", "Sub0_Rel", "Sub1_Abs", 
"Sub1_Rel", "TP", "TA", "Sub_Inflow"), row.names = c(NA, 6L), class = "data.frame") 

> dput(head(datalist[[2]])) 
structure(list(Time = c(0L, 60L, 120L, 180L, 240L, 300L), Sub0_Abs = c(1.49899, 
1.49284, 1.49234, 1.49207, 1.49176, 1.49141), Sub0_Rel = c(1, 
0.9959, 0.9956, 0.9954, 0.9952, 0.9949), Sub1_Abs = c(1.49899, 
1.49899, 1.49899, 1.49899, 1.49899, 1.49899), Sub1_Rel = c(1, 
1, 1, 1, 1, 1), TP = c(0.15, 0.1647, 0.1658, 0.1664, 0.1671, 
0.1679), TA = c(0.13, 0.21, 0.25, 0.25, 0.25, 0.37), Sub_Inflow = c(0, 
0, 0, 0, 0, 0)), .Names = c("Time", "Sub0_Abs", "Sub0_Rel", "Sub1_Abs", 
"Sub1_Rel", "TP", "TA", "Sub_Inflow"), row.names = c(NA, 6L), class = "data.frame") 

相關列是時間,Sub0_Rel和Sub1_Rel。在我之前的問題中,我試圖縮短名稱。

+1

你會真正從學習使用'lapply'受益,'sapply '。它們實際上很容易使用。如果您在問題中提供了一些可重複的數據,那麼人們可以更容易地爲您提供幫助。 – Roland

+0

羅蘭你好,謝謝你的幫助。我試圖通過學習示例來學習lapply,但是學習起來有些困難,因爲它一見並不那麼「直觀」。 ...我添加了一些示例數據,以便可以想象數據結構。 – Hanna

回答

0

正如@Roland所說,沒有一些示例數據很難幫助你。我爲一堆z值編寫了一些代碼,但是,當然(沒有數據),代碼沒有經過測試。也許它會幫助你開始。

# try with a bunch of z values 
z <- c(0.25, 0.45, 0.72, 0.83) 
a <- 1-z 

setwd("H:/...") 
# read in all of the data and save to a list 
names <- dir(pattern="Data.txt") 
datalist <- lapply(names, read.table, header=TRUE) 
matchs <- lapply(datalist, function(dat) 
    cbind(dat[which.min(abs(dat$Sub1-a)), ]), dat[which.min(abs(dat$Sub2-a)), ]) 

右在這裏我迷路了,因爲我不知道你想要繪製什麼......

+0

謝謝你的幫助。我嘗試了你的代碼,但是我收到錯誤信息'Object'dat'not found' ... – Hanna

+0

如果你將結果發佈到以下兩個命令中,我會嘗試排除故障。 'dput(head(datalist [[1]]))''和'dput(head(datalist [[2]]))''。 –

+0

Thx,我編輯了我的問題並添加了dput的輸出。 – Hanna

0

好吧,我有一個想法,可能會使事情簡單一點。如何使用線性插值而不是爲長序列中的每個數字找到最接近的子值?你可以用approx()函數來做到這一點。例如,定義一個函數來計算一個子序列的平均時間。

mean.time <- function(sub, time, points=seq(0.01, 0.99, by=0.01)) { 
    linear.interp <- approx(x=sub, y=time, xout=points) 
    mean(linear.interp$y, na.rm=TRUE) 
    } 

然後,您可以將此函數應用於數據框列表的每個元素,一次爲sub1,一次爲sub2。 (我假定你有興趣Sub0_RelSub1_Rel。如果不是的話,你將不得不修改代碼的那部分。)

match1 <- sapply(datalist, function(dat) mean.time(dat$Sub0_Rel, dat$Time)) 
match2 <- sapply(datalist, function(dat) mean.time(dat$Sub1_Rel, dat$Time))