找到对应于给定百分位数的DOY

时间:2018-06-01 03:58:45

标签: r percentile

我有一个2013年至2017年每日NDVI值的数据框。 我的数据框具有连续的NDVI数据(即,一年中的每一天),但这是我的数据帧结构的可重现的示例:

year <- sample(2013:2017, 750,replace=TRUE)
DOY <- sample(1:365, 750,replace=TRUE)
NDVI<- runif(750, -1, 1)
df <- cbind(year,DOY,NDVI)

我使用分位数和tapply函数为数据帧中的每一年找到对应于10%,30%,50%和80%百分位数的NDVI值:

quantile=do.call("rbind", tapply(df$NDVI, df$year, quantile,c(0.10, 0.30, 0.50, 0.80)))

我的问题是:我怎样才能找到与每年NDVI值的10%,30%,50%,80%相对应的DOY?例如,如果NDVI值为0.3对应于2014年的第50百分位数,我想返回对应于NDVI为0.3的DOY。

感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

问题是,有时百分位数与NDVI中的真实观察结果不匹配。在这些情况下,平均值是NDVI值的变量,例如X年的第30个百分位数。在这些情况下,我采用了最接近第30个百分点的两个NDVI值,您可以选择同时选择两者或采取相应DOY值的平均值。也许这是一个小小的解决方法,但这是我现在能想到的最好的方法:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

      String db_file = "word504.db" ;
      String db_path= this.getDatabasePath(db_file ).getPath();

        File dbFile = new File(db_path);
       if(!dbFile.exists())
        {
            try
            {
                copyFileFromAssets(db_file, db_path);
            }
            catch (IOException e) {
                Log.e("***********" , ""+ e.getMessage());
            }
        }


    }

    private void copyFileFromAssets(String name,String dest) throws IOException
    {
        InputStream mInput = this.getAssets().open(name);
        OutputStream mOutput = new FileOutputStream(dest);

        byte[] mBuffer = new byte[1024];
        int mLength;
        while ((mLength = mInput.read(mBuffer))>0)
        {
            mOutput.write(mBuffer, 0, mLength);
        }
        mOutput.flush();
        mOutput.close();
        mInput.close();
    }
}

给出了:

set.seed(1)
year <- sample(2013:2017, 750,replace=TRUE)
DOY <- sample(1:365, 750,replace=TRUE)
NDVI<- runif(750, -1, 1)
df <- as.data.frame(cbind(year,DOY,NDVI))
library(dplyr)
library(tidyr)
library(broom)
df %>% 
  group_by(year) %>% 
  do( tidy(t(quantile(.$NDVI, c(0.10, 0.30, 0.50, 0.80)))) ) %>% 
  ungroup() %>% 
  right_join(df) %>% 
  arrange(year, NDVI) %>% 
  group_by(year) %>% 
  filter(abs(X10. - NDVI) == min(abs(X10. - NDVI)) |
       abs(X30. - NDVI) == min(abs(X30. - NDVI)) |
       abs(X50. - NDVI) == min(abs(X50. - NDVI))|
       abs(X80. - NDVI) == min(abs(X80. - NDVI)))

答案 1 :(得分:1)

这与Len的解决方案类似,我重申他们对完全匹配的困难所说的话。我使用相同的种子来使结果具有可比性。区别在于我将分位数保持为长整数,这使得过滤步骤更容易。

library("tidyverse")
set.seed(1)
year <- sample(2013:2017, 750,replace=TRUE)
DOY <- sample(1:365, 750,replace=TRUE)
NDVI<- runif(750, -1, 1)
df <- data_frame(year,DOY,NDVI)

df %>% group_by(year) %>% 
  do(data_frame(p = c(10, 30, 50, 80)/100, q = quantile(.$NDVI, probs = p))) %>% 
  full_join(df) %>% 
  group_by(year, p) %>% 
  slice(which.min(abs(NDVI - q)))


# A tibble: 20 x 5
# Groups:   year, p [20]
    year     p        q   DOY     NDVI
   <int> <dbl>    <dbl> <int>    <dbl>
 1  2013 0.100 -0.844     247 -0.844  
 2  2013 0.300 -0.459      96 -0.447  
 3  2013 0.500 -0.0144    202 -0.0144 
 4  2013 0.800  0.583      59  0.584  
 5  2014 0.100 -0.811     128 -0.818  
 6  2014 0.300 -0.403      37 -0.410  
 7  2014 0.500 -0.0136    187 -0.0136 
 8  2014 0.800  0.623     278  0.620  
 9  2015 0.100 -0.890     280 -0.887  
10  2015 0.300 -0.494     330 -0.488  
11  2015 0.500 -0.0332    316 -0.0332 
12  2015 0.800  0.646     190  0.647  
13  2016 0.100 -0.803     351 -0.803  
14  2016 0.300 -0.447     206 -0.447  
15  2016 0.500 -0.00170   122 -0.00170
16  2016 0.800  0.548     353  0.548  
17  2017 0.100 -0.824     326 -0.830  
18  2017 0.300 -0.484     124 -0.483  
19  2017 0.500 -0.00704   175 -0.00900
20  2017 0.800  0.573      95  0.570