[英]Create summary table in R using statistics from package `modifiedmk`
我正在嘗試從 R 中的modifiedmk
包中運行一個函數。
install.packages('modifiedmk')
library(modifiedmk)
我有一個數據框data
,我使用以下內容生成:
Station <- c('APT','APT', 'APT','APT', 'APT', 'APT', 'APT','APT', 'APT','APT','APT','APT',
'AF','AF', 'AF','AF','AF','AF','AF','AF','AF',
'EL', 'EL', 'EL', 'EL', 'EL', 'EL', 'EL', 'EL', 'EL', 'EL', 'EL', 'EL', 'EL', 'EL', 'EL',
'GFS', 'GFS', 'GFS', 'GFS', 'GFS', 'GFS', 'GFS', 'GFS', 'GFS', 'GFS', 'GFS', 'GFS', 'GFS', 'GFS', 'GFS', 'GFS'
)
Rainfall <- c(375.3, 263.3, 399.2, 242.6, 847.6, 276.5, 712.8, 366.3, 188.6, 478.4, 539, 682.5,
520.7, 1337.8, 524, 908.4,748.5,411.8, 772.4,978.5,983,
732.4, 788.6, 567.1, 576, 931.6, 727.2, 1079.3, 902.8,493.4, 630.7, 784.1,660.2, 531.3, 487.1,798.4,
1064.1, 590.3, 1011.2, 1037.1, 1398.4, 1153.6,994.1, 1100.2,743.7,637.4, 792.2, 891.9,880.9, 670, 920.2,681.4)
Year <- c('1957','1958','1959','1960','1961','1962','1963','1964','1965','1966','1967','1968',
'1960','1961','1962','1963','1964','1965','1966','1967','1968',
'1957','1958','1959','1960','1961','1962','1963','1964','1965','1966','1967','1968','1969','1970','1971',
'1964','1965','1966','1967','1968','1969','1970','1971','1972','1973','1974','1975','1976','1977','1978','1979')
length(Year)
data<-data.frame(Year, Station, Rainfall)
我有四個降雨數據Stations
作為數據框中的行。 我想在每個數據Station
上應用modifiedmk
包中的mmky1lag
方法,並在 R 中生成一個包含兩列的匯總表:
例如,我可以使用mmky1lag(as.vector(data$Rainfall))
在所有降雨數據上運行mmky1lag
方法,它產生
> mmky1lag(as.vector(data$Rainfall))
Corrected Zc new P-value N/N* Original Z old P.value
3.332353e+00 8.611480e-04 1.297360e+00 3.795608e+00 1.472822e-04
Tau Sen's slope old.variance new.variance
3.634992e-01 9.092857e+00 1.605933e+04 2.083474e+04
我對其中兩個輸出感興趣:
第 1 列:
# Get percent of stations with significant trends where p < 0.05
mmky1lag(as.vector(data$Rainfall))[2] < 0.05
和第 2 列:
# Make another column that is the mean Sen's slope
mmky1lag(as.vector(data$Rainfall))[7]
但是,如何在data
上應用此方法,從而為每個單獨的Station
獲得結果? 在python中,我會groupby Station
然后應用該方法。 但我不確定如何在 R 中做到這一點。
然后按站分組后,我想要一個包含上述兩列信息的匯總表。
如果您想按組(在本例中為station
)將mmky1lag
函數應用於數據幀,則需要考慮多種方法。
首先,您可以使用aggregate
:
library(modifiedmk)
mktests <- aggregate(Rainfall ~ Station, data = data, FUN = mmky1lag)
這將采用按Station
組的Rainfall
度量的公式。 您的所有結果都將在矩陣中返回,MK 測試參數位於單列中。
另一種方法可能是使用data.table
包。
library(data.table)
mktests <- as.data.table(data)[, as.list(mmky1lag(Rainfall)), by = Station]
這將從mmky1lag
獲取結果並將其放入列表,然后轉換為數據表。 選項by
將允許您通過Station
執行此操作。
第三種方法可能是使用dplyr
包。
library(dplyr)
mktests <- data %>%
group_by(Station) %>%
group_map(~mmky1lag(.x$Rainfall)) %>%
setNames(unique(sort(data$Station))) %>%
bind_rows(.id = "Station")
這使用group_by
按Station
分組,然后group_map
將mmky1lag
函數應用於分組元素。 需要setNames
將Station
值添加回結果,然后bind_rows
將結果列表轉換為數據框。
結果(使用data.table
解決方案)應該如下所示(其他方法應該類似):
R> mktests
Station Corrected Zc new P-value N/N* Original Z old P.value Tau Sen's slope old.variance new.variance
1: APT 1.2801214 0.2005025 0.4849366 0.8914431 0.3726915 0.2121212 17.32083 212.6667 103.12986
2: AF 1.2424858 0.2140574 0.5703144 0.9383149 0.3480826 0.2777778 29.73750 92.0000 52.46892
3: EL -0.7452428 0.4561249 1.1288325 -0.7917947 0.4284804 -0.1619048 -9.60000 408.3333 460.93994
4: GFS -1.3242038 0.1854354 1.4160741 -1.5757881 0.1150746 -0.3000000 -19.65333 493.3333 698.59657
如果您想要 p < .05 的Station
百分比,您可以執行以下操作:
sum(mktests$`new P-value` < .05) / nrow(mktests)
在這種情況下,它為零,因為基於new P-value
,它們都不顯着。
可以計算Sen's slope
的平均值:
mean(mktests$`Sen's slope`)
4.45125
我不確定您是否預期示例數據會產生不同的結果(正如您建議將結果放入 2 列)。 請讓我知道這是否是您的想法。
你可以嘗試在基礎 R 中做這樣的事情。
首先,您可以將數據作為列表,每個元素都是一個Station
:
data_list <- split(data,data$Station)
然后你可以使用lapply()
,引用自doc :
lapply 返回一個與 X 長度相同的列表,其中的每個元素都是將 FUN 應用於 X 的對應元素的結果。
library(modifiedmk)
stat_list <- lapply(data_list, function(x) mmky1lag(x$Rainfall))
現在,您可以將作為data.frame
為例,然后計算您需要的內容。 您可以使用do.call()
將rbind()
應用於列表,並將其放入data.frame()
。 通常我更喜歡使用列的名稱而不是它們的索引,但這是主觀的。
從文檔rbind()
:
取一系列向量、矩陣或數據幀參數,並分別按列或行組合。 這些是具有其他 R 類方法的通用函數。
從文檔do.call()
:
do.call 從名稱或函數以及要傳遞給它的參數列表構造並執行函數調用。
stat_df <- data.frame(do.call(rbind, stat_list))
現在您可以輕松計算您需要的內容:
# percentage of the < 0.05 p-values
# here you calculate the number of row of the subset of interest of the
# df / number of row of the dataset.
nrow(stat_df[stat_df$new.P.value < 0.05,])/nrow(stat_df)*100
[1] 0
# Or if you want a prettier result printed:
library(formattable)
percent(nrow(stat_df[stat_df$new.P.value < 0.05,])/nrow(stat_df))
[1] 0.00%
# the mean of Sen.s.slope
mean(stat_df$Sen.s.slope)
[1] 4.45125
另外,我不明白你想要的輸出,它被寫成 Column1 和 Column2。 如果您定義它,就有可能得到更符合您要求的結果。
這接近嗎? 百分比將為零,因為所有 p 值都大於 5%。 您需要在循環中添加< 0.05
才能在數據框中獲得真/假值。
results <- data.frame(matrix(NA, 4, 3))
colnames(results) <- c('station', 'p-val', 'Sen-slope')
for(ii in seq_along(unique(Station))){
i <- unique(Station)[ii]
results[ii, 1] <- i
results[ii, 2] <- mmky1lag(as.vector(data$Rainfall[data$Station %in% i]))[2]
results[ii, 3] <- mmky1lag(as.vector(data$Rainfall[data$Station %in% i]))[7]
}
> results
station p-val Sen-slope
1 APT 0.2005025 17.32083
2 AF 0.2140574 29.73750
3 EL 0.4561249 -9.60000
4 GFS 0.1854354 -19.65333
如果您使用 tidyverse,則很容易執行類似 Pandas 的語法。
# Importing tidyverse
library(tidyverse)
# Calculating grouped values
data %>%
group_by(Station) %>%
summarise('p-value' = mmky1lag(Rainfall)[2]<0.05, "Sen's slope" = mmky1lag(Rainfall)[7])
# Output
Station p.value Sen.s.slope
AF FALSE 29.73750
APT FALSE 17.32083
EL FALSE -9.60000
GFS FALSE -19.65333
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.