使用来自`modifiedmk`包的统计信息在R中创建汇总表

时间:2020-11-04 20:56:33

标签: r group-by statistics pivot summary

我正在尝试从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降雨数据作为行。我想对每个mmky1lag的数据应用modifiedmk包中的Station方法,并在R中生成一个包含两列的汇总表:

  1. 具有显着趋势的站点,其中p <0.05
  2. 平均森氏斜率

例如,我可以使用生成的mmky1lag对所有的Rainfall数据运行mmky1lag(as.vector(data$Rainfall))方法

> 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中,我将对Station进行分组,然后应用该方法。但是我不确定如何在R中做到这一点。

然后按站进行分组后,我想要一个包含上述两列信息的汇总表。

4 个答案:

答案 0 :(得分:2)

如果要将mmky1lag函数按组应用于数据帧(在这种情况下为station),可以考虑多种方法。

首先,您可以使用aggregate

library(modifiedmk)

mktests <- aggregate(Rainfall ~ Station, data = data, FUN = mmky1lag)

这将采用Rainfall组度量Station的公式。您所有的结果都将以矩阵形式返回,其中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_byStation进行分组,然后使用group_mapmmky1lag函数应用于分组的元素。需要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

如果您希望Station的百分比为p <.05,可以这样做:

sum(mktests$`new P-value` < .05) / nrow(mktests)

在这种情况下,它为零,因为根据new P-value,它们都不是有效的。

可以计算Sen's slope的平均值:

mean(mktests$`Sen's slope`)
4.45125

我不确定您的示例数据是否会得出不同的结果(因为您建议将结果分成两列)。请让我知道这是否是您的想法。

答案 1 :(得分:2)

您可以尝试在基本R中做类似的事情。
首先,您可以将数据作为列表,每个元素都是一个Station

data_list <- split(data,data$Station)

然后您可以使用lapply(),引用the doc

lapply返回一个与X长度相同的列表,其中每个元素 是将FUN应用于X的相应元素的结果。

library(modifiedmk)
stat_list <- lapply(data_list, function(x) mmky1lag(x$Rainfall))

现在,您可以输入data.frame,然后计算所需的内容。 您可以使用do.call()rbind()应用于列表,并将其放入data.frame()中。通常,我更喜欢使用列名而不是索引,但这是主观的。
来自the doc rbind()

采用向量,矩阵或数据帧参数的序列并合并 分别按列或行。这些是具有 其他R类的方法。

来自the doc 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。如果定义了它,则可能会得到更适合您要求的结果。

答案 2 :(得分:1)

这接近吗?该百分比将为零,因为所有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

答案 3 :(得分:0)

如果使用tidyverse,则很容易进行类似熊猫的语法。

{"accountingCurrency":"USD","address1":"test address","billedCurrency":"EUR","billedRecurringPrice":"0.00","bin":"444444","cardType":"VISA","city":"testcity","country":"FR","initialPeriod":"30","lastName":"test","timestamp":"2020-11-12 06:05:49","username":"llllll","threeDSecure":"NOT_APPLICABLE"}