Fit gamma mixture to fertility schedule in R - r

I am trying to fit a gamma mixture model (two gamma distributions) to an age-fertility profile. I have a dataset containing age specific fertility rates and age, and I want to fit two gammas in order to find the corresponding parameters (in the end I will use fertility profiles from different years and try to see how the parameters evolve over time). I have so far tried to use mixtools library (gammamixEM) but without success. I would be very grateful for some help.
Ale
a<- structure(list(EDAD = structure(1:45, .Label = c("11", "12", "13", "14", "15",
"16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29",
"30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43",
"44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "Total" ),
class = "factor"), value = c(0, 0, 0, 0, 0.002761668, 0.006712018, 0.010820244,
0.017867778, 0.029533765, 0.034055242, 0.036665669, 0.043840421, 0.042949584,
0.042344612, 0.050588917, 0.050187588, 0.054114728, 0.057258792, 0.059280324,
0.062566731, 0.062369629, 0.062154767, 0.063734337, 0.058236776, 0.052623842,
0.046330921, 0.040639027, 0.033707865, 0.02531141, 0.017651534, 0.010953808,
0.007463863, 0.003224766, 0.002190101, 0.001117443, 0.000465116, 0.000363901,
0.00012647, 0.000267326, 0.000280308, 0, 0, 0, 0, 0)), .Names = c("EDAD", "value"),
class = "data.frame", row.names = 79596:79640)

The reason why it won't run is because you have zeroes in your data set. Here is what you could do:
aa <- a$value[a$value > 0]
Now you can fit the gamma mixture
require(mixtools)
g3 <- gammamixEM(aa)
Now check that it looks OK by plotting the fitted mixture density.
d3 <- function(x) g3$lambda[1]*dgamma(x, g3$gamma.pars[1], 1/g3$gamma.pars[2]) + g3$lambda[2]*dgamma(x, g3$gamma.pars[3], 1/g3$gamma.pars[4])
Here is another pitfall: gammamixEM apparently parametrises the gamma distribution differently to R. Why? Who knows?
x <- seq(min(aa), max(aa), 0.001)
plot(x, d3(x), "l")
hist(aa, col="pink", add=T, freq=F, breaks=10)
Looks reasonable, if far from perfect.

Related

Group periodic data in dataframe

I have a dataset comprised of periodic data. I want to group the data by period.
The full dataset is provided: LINK
Data for one period of the dataset is provided and ploted:
> dput(DATA[1:122,c(2,9)])
structure(list(Actuator.Force = c(-4853.5854, -4566.9771, -4198.7612,
-3774.5527, -3317.6958, -2847.5229, -2364.7585, -1880.9485, -1405.4272,
-930.289, -467.04822, -18.867363, 421.17499, 838.86719, 1239.9121,
1626.0669, 1990.6389, 2334.0852, 2655.344, 2962.0227, 3243.7817,
3506.2249, 3744.2622, 3959.8271, 4156.7061, 4324.9048, 4469.229,
4591.6689, 4687.4194, 4764.0801, 4814.6167, 4840.313, 4846.0181,
4826.3135, 4777.6553, 4696.0791, 4583.854, 4442.457, 4272.5254,
4076.7224, 3851.1211, 3603.1853, 3330.7456, 3038.3157, 2724.115,
2386.5476, 2032.5809, 1660.0547, 1268.0084, 859.16675, 432.4075,
-14.131592, -479.29309, -955.67108, -1444.614, -1937.2562, -2437.0085,
-2941.8914, -3450.9009, -3959.9597, -4468.9795, -4981.2549, -5492.6997,
-6002.334, -6510.5425, -7016.2432, -7517.8286, -8013.1348, -8500.4199,
-8974.8867, -9439.5479, -9890.5938, -10326.367, -10744.421, -11147.754,
-11534.83, -11902.651, -12248.997, -12577.919, -12885.458, -13172.309,
-13441.554, -13691.502, -13922.634, -14127.116, -14305.272, -14458.267,
-14582.934, -14685.274, -14758.539, -14806.058, -14830.719, -14836.625,
-14822.204, -14773.916, -14700.484, -14597.968, -14469.834, -14312.099,
-14126.422, -13915.136, -13676.505, -13412.388, -13120.703, -12807.961,
-12473.883, -12115.751, -11740.082, -11342.633, -10929.945, -10502.158,
-10062.869, -9611.8271, -9146.6006, -8673.3545, -8191.7417, -7700.769,
-7200.9346, -6695.8809, -6185.2378, -5670.8711, -5154.9995),
Rotation = c(-0.005985651, -0.00565783616666667, -0.00522075016666667,
-0.0046743925, -0.00406732866666667, -0.00343598223333333,
-0.00286534205, -0.00219757165, -0.00156622503333333, -0.000934878566666667,
-0.000267108158333333, 0.000303531998333333, 0.00084988955,
0.0013962471, 0.00193046351666667, 0.00242825596666667, 0.00288962463333333,
0.0033995583, 0.0038366445, 0.00424944783333333, 0.004637969,
0.0050507725, 0.005378587, 0.00565783616666667, 0.00594922716666667,
0.00620419383333333, 0.006410596, 0.0065684325, 0.00670198666666667,
0.00683554116666667, 0.0069205295, 0.00699337683333333, 0.0070055185,
0.006993377, 0.00696909483333333, 0.00688410516666667, 0.006774834,
0.00659271483333333, 0.006386313, 0.00613134633333333, 0.0058399555,
0.0055364235, 0.00518432633333333, 0.00483222916666667, 0.0044072845,
0.00403090483333333, 0.00353311216666667, 0.0029988961, 0.00251324506666667,
0.0020275938, 0.00144481233333333, 0.00086203085, 0.000303531998333333,
-0.000315673273333333, -0.000983443666666667, -0.00162693151666667,
-0.00233112578333333, -0.0029988961, -0.00366666666666667,
-0.00433443683333333, -0.00496578316666667, -0.00563355366666667,
-0.0062770415, -0.0069690945, -0.0076611475, -0.00836534183333333,
-0.00902097083333333, -0.00968874116666667, -0.0103443703333333,
-0.0109514346666667, -0.011594922, -0.012177704, -0.0127969093333333,
-0.0133918318333333, -0.0139746131666667, -0.0145209698333333,
-0.014982339, -0.0154437081666667, -0.0159050765, -0.0163178798333333,
-0.0167185421666667, -0.0170706398333333, -0.0174105943333333,
-0.0177505506666667, -0.018017659, -0.0182483433333333, -0.0184547455,
-0.0186490056666667, -0.0187704183333333, -0.01887969, -0.0189525386666667,
-0.018988962, -0.0190011033333333, -0.018988962, -0.0189768206666667,
-0.0189282553333333, -0.0188189838333333, -0.018673289, -0.018442604,
-0.0182240605, -0.017993377, -0.0176534206666667, -0.0173256068333333,
-0.0169492263333333, -0.0165485635, -0.0161357608333333,
-0.0156622516666667, -0.0152373058333333, -0.0147152313333333,
-0.0141931568333333, -0.0136103748333333, -0.0130275935,
-0.0123962468333333, -0.0118013235, -0.0112064015, -0.0105507718333333,
-0.00993156683333333, -0.0092637965, -0.008620309, -0.00791611466666667,
-0.00719977883333333, -0.0065441495)), row.names = c("1",
"2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13",
"14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24",
"25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35",
"36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46",
"47", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57",
"58", "59", "60", "61", "62", "63", "64", "65", "66", "67", "68",
"69", "70", "71", "72", "73", "74", "75", "76", "77", "78", "79",
"80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "90",
"91", "92", "93", "94", "95", "96", "97", "98", "99", "100",
"101", "102", "103", "104", "105", "106", "107", "108", "109",
"110", "111", "112", "113", "114", "115", "116", "117", "118",
"119", "120", "121", "122"), class = "data.frame")
The next row of the data starts a new period and so on. I want to group the rows by the periods that exist in the data.
Although the code provided in this example can find the periods if fully completed data is provided (it worked for the first three periods), when applied to the entire dataset of periodic data, it resulted in NaNs.
ssp <- spectrum(DATA$Rotation, plot = FALSE, method = "ar", n.freq = 1e6)
period <- 1 / with(ssp, freq[spec == max(spec)])
DATA$Loop <- (seq_len(nrow(DATA)) %/% period) + 1
Here's an approach where I define a region where both the Rotation is increasing and Rotation is at least as high as the starting value. Then I count how many times we enter that region and that's the period number.
library(dplyr)
Rot_start = DATA$Rotation[1]
rbind(DATA, DATA) %>% # to demonstrate two cycles
mutate(Rot_pos = Rotation > lag(Rotation, default = -1),
Rot_rightside = Rotation >= Rot_start,
Rot_region = Rot_pos & Rot_rightside,
new_period = Rot_region & !(lag(Rot_region, default = FALSE)),
period = cumsum(new_period))
# more succinct, same workings
# mutate(Rot_region = Rotation > lag(Rotation, default = -1) & Rotation >= Rot_start,
# period = cumsum(Rot_region & !(lag(Rot_region, default = FALSE))))

Error in as.vector(data) when creating a mask for SECR

I am trying to create a mask in SECR using a .shp file. Always getting this error: Error in as.vector(data) :
no method for coercing this S4 class to a vector when i use the make.mask
this is my code:
fence <- rgdal :: readOGR('/Rdata/SECR', layer = 'building')
OGR data source with driver: ESRI Shapefile Source: "/Rdata/SECR",
layer: "building" with 2492 features
It has 1 fields
library(secr)
#This is secr 3.2.1. For overview type ?secr
> qmask = make.mask(Quenda_traps,
+ buffer = 300,
+ type = "trapbuffer",
+ poly = fence,
+ poly.habitat = "FALSE")
Error in as.vector(data) : no method for coercing this S4 class to
a vector
dput(Quenda_traps)
structure(list(x = c(390576.21, 390637.85, 390594.93, 390528.49,
390646.58, 390488.12, 390681.01, 390499.98, 390632.29, 390677.26,
390642.7, 390710.33, 390690.37, 390741.81, 390588.01, 390655.06,
390575.97, 390246.66, 390340.13, 390236.33, 390309.59, 390295.93,
390164.11, 390065.71, 390120.42, 390117.17, 390091.7, 389875.57,
390179.69, 390157.45, 390164.94, 390151.02, 390172.17, 390246.28,
390263.25, 390256.32, 390308.2, 390135.06, 390093.3, 389914.13,
389916.76, 389869.37, 389809.17, 389782.5, 389818.78, 389802.75,
389818.78, 389771.52, 389792.74, 389791.25, 389905.36, 389832.62,
389886.16, 389863.21, 389908.68, 389912.46, 389902.05, 389528.11,
389661.6, 389689.54, 389657.88, 389678.71, 389569.25, 389618.44,
389564.87, 389615.37, 389662.18, 389630.96, 389713.09, 389654.91,
389744.37, 389762.02, 389715.87, 389696.2), y = c(6451727.44,
6451613.91, 6451566.89, 6451511.85, 6451416.66, 6451402.77, 6451287.32,
6451177.83, 6451164.84, 6451108.78, 6451188.57, 6450929.54, 6450855.04,
6450723.66, 6450716.47, 6450451.11, 6450343.83, 6451821.46, 6451645.08,
6451553.05, 6451588.21, 6451541.5, 6451509.03, 6451442.56, 6451358.89,
6451222.49, 6451221.11, 6451303.03, 6451115.63, 6450989, 6450994.62,
6450797.13, 6450761.88, 6450717.22, 6450719.62, 6450399.14, 6450403.03,
6450352.38, 6450197.83, 6451841.15, 6451684.86, 6451526.92, 6451419.83,
6451441.72, 6451316.83, 6451367.43, 6451316.83, 6451235.39, 6451105.9,
6450981.72, 6450992.93, 6450910.1, 6450935.07, 6450787.37, 6450685.86,
6450684.79, 6450600.42, 6451656.26, 6451534.65, 6451395.26, 6451267.42,
6451262.1, 6451257.59, 6451248.14, 6451138.91, 6451096.22, 6451132.2,
6450964.46, 6450964.24, 6450844.98, 6450864.8, 6450717.54, 6450620.58,
6450519.48)), class = c("traps", "data.frame"), row.names = c("1001",
"1002", "1003", "1004.1", "1004.2", "1005.1", "1005.2", "1006.1",
"1006.2", "1006.3", "1006.4", "1007", "1008", "1009", "1010",
"1011", "1012", "2001", "2002", "2003.1", "2003.2", "2003.3",
"2004", "2005", "2006", "2007.1", "2007.2", "2008.1", "2008.2",
"2009.1", "2009.2", "2010.1", "2010.2", "2011.1", "2011.2", "2012.1",
"2012.2", "2013", "2014", "3001", "3002", "3003", "3004.1", "3004.2",
"3005.1", "3005.2", "3005.3", "3006", "3007", "3008.1", "3008.2",
"3009.1", "3009.2", "3010", "3011.1", "3011.2", "3012", "4001",
"4002", "4003", "4004.1", "4004.2", "4005.1", "4005.2", "4006",
"4007.1", "4007.2", "4008.1", "4008.2", "4009.1", "4009.2", "4010",
"4011", "4012"), detector = "multi", usage = structure(c(1, 1,
1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1,
1, 1, 1, 0, 1... ), .Dim = c(74L, 85L), .Dimnames = list(
c("1001", "1002", "1003", "1004.1", "1004.2", "1005.1", "1005.2",
"1006.1", "1006.2", "1006.3", "1006.4", "1007", "1008", "1009",
"1010", "1011", "1012", "2001", "2002", "2003.1", "2003.2",
"2003.3", "2004", "2005", "2006", "2007.1", "2007.2", "2008.1",
"2008.2", "2009.1", "2009.2", "2010.1", "2010.2", "2011.1",
"2011.2", "2012.1", "2012.2", "2013", "2014", "3001", "3002",
"3003", "3004.1", "3004.2", "3005.1", "3005.2", "3005.3",
"3006", "3007", "3008.1", "3008.2", "3009.1", "3009.2", "3010",
"3011.1", "3011.2", "3012", "4001", "4002", "4003", "4004.1",
"4004.2", "4005.1", "4005.2", "4006", "4007.1", "4007.2",
"4008.1", "4008.2", "4009.1", "4009.2", "4010", "4011", "4012"
), c("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11",
"12", "13", "14", "15", "16", "17", "18", "19", "20", "21",
"22", "23", "24", "25", "26", "27", "28", "29", "30", "31",
"32", "33", "34", "35", "36", "37", "38", "39", "40", "41",
"42", "43", "44", "45", "46", "47", "48", "49", "50", "51",
"52", "53", "54", "55", "56", "57", "58", "59", "60", "61",
"62", "63", "64", "65", "66", "67", "68", "69", "70", "71",
"72", "73", "74", "75", "76", "77", "78", "79", "80", "81",
"82", "83", "84", "85"))), spacex = 0.240000000048894, spacey = 0.21999999973923, spacing = 79.5867492192872)

combine two data frames into one while keeping the original row numbers

I'm struggling with a very simple problem. I have two data frames to be combined into a single data frame while retaining their original row names. If you're interested to play with the two data frames:
> dput(cc)
structure(list(c = c(166.081273211195, 117.874627144804, 85.7050194973198,
122.960746859139, 144.149802403233, 90.8034500957001, 89.5265981283352,
77.8535718910714, 144.544005656701, 115.597165020403, 109.028391182666,
89.4045716355402, 77.7944830105746, 69.3378920684953, 79.9094499459695,
146.768077595585, 157.933946809176, 92.562729606313, 62.5081476457419,
90.1081848285295, 111.830482369239, 111.596975757741, 99.2311075024839,
145.204385556523, 99.0215341758211, 75.4302512245677, 92.0094563363458,
77.7314808830408)), .Names = "c", row.names = c("26", "27", "28",
"29", "35", "36", "37", "38", "39", "40", "46", "47", "48", "49",
"50", "51", "52", "56", "57", "58", "59", "60", "61", "62", "69",
"70", "71", "72"), class = "data.frame")
> dput(ccc)
structure(list(b = c(76.376257255471, 61.8314936138378, 62.769450181685,
73.6356164203567, 111.690756826382, 76.9294523843767, 61.3534699857719,
69.3647221333577, 83.9764878084258, 81.3800252294203, 69.5091780233591,
87.3595961209547, 78.5074999563006, 74.4479256924594, 81.5920316281566,
96.3417259554163, 75.4138056616399, 76.0553034201146, 95.1759950844736,
81.3252467041995, 86.306305649635, 70.5626459312969, 72.7797520793756,
119.49702877934, 123.268678343102, 88.0450051118928, 76.2139948860248,
98.1496728839206, 126.396927030103, 146.058540478643, 115.7341525964,
87.280600158726, 78.0274068331766, 122.817977752389, 142.491559175427,
152.895839114334, 94.4932174696818, 117.167042165763, 85.5340971715004,
101.480170738897, 117.759691799033, 128.998051359269, 98.3180491401911,
84.5915489017958, 87.4927520958843, 75.5366495973031, 118.088343275321,
121.375320935357, 94.7724147096235, 70.2266610201599, 123.158462686523,
76.87408931845, 94.4365460662552, 105.952134808703, 76.821070196668
)), .Names = "b", row.names = c("1", "2", "3", "4", "5", "6",
"7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17",
"18", "19", "20", "21", "22", "23", "24", "25", "30", "31", "32",
"33", "34", "41", "42", "43", "44", "45", "53", "54", "55", "63",
"64", "65", "66", "67", "68", "73", "74", "75", "76", "77", "78",
"79", "80", "81", "82", "83"), class = "data.frame")
The easiest way to combine is
> c(cc$c, ccc$b)
[1] 166.08127 117.87463 85.70502 122.96075 144.14980 90.80345 89.52660 77.85357 144.54401
[10] 115.59717 109.02839 89.40457 77.79448 69.33789 79.90945 146.76808 157.93395 92.56273
[19] 62.50815 90.10818 111.83048 111.59698 99.23111 145.20439 99.02153 75.43025 92.00946
[28] 77.73148 76.37626 61.83149 62.76945 73.63562 111.69076 76.92945 61.35347 69.36472
[37] 83.97649 81.38003 69.50918 87.35960 78.50750 74.44793 81.59203 96.34173 75.41381
[46] 76.05530 95.17600 81.32525 86.30631 70.56265 72.77975 119.49703 123.26868 88.04501
[55] 76.21399 98.14967 126.39693 146.05854 115.73415 87.28060 78.02741 122.81798 142.49156
[64] 152.89584 94.49322 117.16704 85.53410 101.48017 117.75969 128.99805 98.31805 84.59155
[73] 87.49275 75.53665 118.08834 121.37532 94.77241 70.22666 123.15846 76.87409 94.43655
[82] 105.95213 76.82107
But doing this recreate the row numbers. Is there any simple function to combine while keeping the row names intact? Thanks!
These lines of code should solve the problem
z0 <- as.numeric(c(rownames(cc), rownames(ccc)))
z <- data.frame(c(cc$c, ccc$b))
row.names(z) <- z0
data.frame(z[order(as.numeric(row.names(z))),])

Doing curve fitting in R for a power series

I have trying to estimate the annual of an investment scheme which applied dollar cost averaging, which the increment of value is listed as below (sorry that MathJax looks like greek to me, so I didn't use it):
x: regular contribution, which is 1500 in my case
y: rate of return PLUS 100% (e.g 1.07 for a 7% return), which is the parameters that I want to estimate.
Time 1: xy
Time 2: (x + xy)*y
Time 3: (x + (x + xy)*y)*y
Time 4: (x + (x + (x + xy)*y)*y)*y
Time 5: (x + (x + (x + (x + xy)*y)*y)*y)*y
Time 6: (x + (x + (x + (x + (x + xy)*y)*y)*y)*y)*y
And the list goes on.
After simplifying the equation, if I calculate it correctly, it should be a power series:
xy(1 + y + y^2 + y^3 + y^4 + y^5 +y^6)
I know that equation above can be used for the nls function in R, as suggested in http://www.walkingrandomly.com/?p=5254. But the problem is, the investment scheme has been traded for more than 6 times, the number of trades is variable and I prefer not to fix the number of trades in the formula.
I wonder if R can create a formula with variable length of the power series, something like a function?
update 01
Thanks for the comment #Roland, I have dput my dataframe as below:
structure(list(date = 1:62, value = c(1500, 3008.1048, 4279.09223337264,
5701.16001583254, 7545.25391699441, 8883.87795645887, 11192.7249445628,
13043.5267669473, 14396.3707754063, 16677.2027610312, 18474.8268536672,
20225.6882177597, 21889.6372952495, 24090.0451286292, 25305.8719822623,
26293.5164474925, 27470.5608573055, 26851.4637959011, 25610.4708389126,
29781.3033136099, 30244.449772352, 31757.1977515, 35216.3065708333,
38661.857424377, 40153.0021899712, 41453.1839013205, 39626.0241467687,
42464.6515262833, 44415.7606695956, 46456.2932413184, 49539.1291983018,
51223.0944673951, 53534.0828137635, 56511.2727118443, 60750.8112270199,
62420.4165280642, 64561.1738159384, 67269.7609015725, 69582.2433935286,
68461.4426685366, 72790.7668201147, 73029.1128824367, 77963.2040906503,
81782.8304828104, 84781.7088147301, 87010.8577769314, 85461.5060309602,
90165.7453255817, 91340.1347579196, 92918.1083054977, 96713.3387975151,
99841.2477244806, 101538.099862003, 104946.468993318, 103233.508326534,
106416.67466519, 109991.955526668, 110800.989092493, 112258.758666778,
118567.887527905, 120872.966926589, 127711.586247323), expected_value = c(1511.96121064336,
3035.97901230344, 4572.1495459301, 6120.56971911465, 7681.33721220313,
9254.55048445835, 10840.3087802712, 12438.7121354211, 14049.861383387,
15673.8581617081, 17310.8049183956, 18960.8049183956, 20623.9622501033,
22300.3818319294, 23990.1694189188, 25693.4316094218, 27410.2758518191,
29140.8104512998, 30885.1445766939, 32643.3882673588, 34415.6524401213,
36202.0488962746, 38002.6903286308, 39817.6903286308, 41647.1633935093,
43491.224933518, 45349.9912792063, 47223.5796887596, 49112.1083553966,
51015.6964148254, 52934.4639527589, 54868.5320124903, 56818.0226025291,
58783.0587042976, 60763.7642798896, 62760.2642798896, 64772.6846512559,
66801.1523452654, 68845.7953255225, 70906.7425760312, 72984.1241093319,
75078.0709747036, 77188.7152664305, 79316.190132135, 81460.6297811776,
83622.169493123, 85800.9456262742, 87997.0956262742, 90210.7580347771,
92442.0724981876, 94691.1797764704, 96958.2217520299, 99243.3414386608,
101546.68299057, 103868.391711469, 106208.614063744, 108567.497677691,
110945.191360831, 113341.845107297, 115757.610107297, 118192.63875665,
120647.084666402)), .Names = c("date", "value", "expected_value"
), row.names = c("63", "62", "61", "60", "59", "58", "57", "56",
"55", "54", "53", "52", "51", "50", "49", "48", "47", "46", "45",
"44", "43", "42", "41", "40", "39", "38", "37", "36", "35", "34",
"33", "32", "31", "30", "29", "28", "27", "26", "25", "24", "23",
"22", "21", "20", "19", "18", "17", "16", "15", "14", "13", "12",
"11", "10", "9", "8", "7", "6", "5", "4", "510", "410"), class = c("tbl_df",
"tbl", "data.frame"))

Computing angle between two vectors (with one vector having a specific X,Y position)

I am trying to compute the angle between two vectors, wherein one vector is fixed and the other vector is constantly moving. I already know the math in this and I found a code before:
theta <- acos( sum(a*b) / ( sqrt(sum(a * a)) * sqrt(sum(b * b)) ) )
I tried defining my a as:
a<-c(503,391)
and my b as:
b <- NM[, c("X","Y")]
When I apply the theta function I get:
Warning message:
In acos(sum(a * b)/(sqrt(sum(a * a)) * sqrt(sum(b * b)))) : NaNs produced
I would appreciate help to solve this.
And here is my sample data:
structure(list(A = structure(c(1L, 1L, 1L, 1L, 1L, 1L), .Label =
c("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12",
"13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23",
"24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34",
"35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45",
"46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56",
"57", "58", "59", "60", "61", "62", "63", "64", "65", "66", "67",
"68", "69", "70", "71", "72", "73", "74", "75", "76", "77", "78",
"79", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89",
"90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "100",
"101", "102", "103", "104", "105", "106", "107", "108", "109",
"110"), class = "factor"), T = c(0.1, 0.2, 0.3, 0.4, 0.5, 0.6 ), X =
c(528.04, 528.04, 528.04, 528.04, 528.04, 528.04), Y = c(10.32,
10.32, 10.32, 10.32, 10.32, 10.32), V = c(0, 0, 0, 0, 0, 0),
GD = c(0, 0, 0, 0, 0, 0), ND = c(NA, 0, 0, 0, 0, 0), ND2 = c(NA,
0, 0, 0, 0, 0), TID = structure(c(1L, 1L, 1L, 1L, 1L, 1L), .Label = c("t1",
"t10", "t100", "t101", "t102", "t103", "t104", "t105", "t106",
"t107", "t108", "t109", "t11", "t110", "t12", "t13", "t14",
"t15", "t16", "t17", "t18", "t19", "t2", "t20", "t21", "t22",
"t23", "t24", "t25", "t26", "t27", "t28", "t29", "t3", "t30",
"t31", "t32", "t33", "t34", "t35", "t36", "t37", "t38", "t39",
"t4", "t40", "t41", "t42", "t43", "t44", "t45", "t46", "t47",
"t48", "t49", "t5", "t50", "t51", "t52", "t53", "t54", "t55",
"t56", "t57", "t58", "t59", "t6", "t60", "t61", "t62", "t63",
"t64", "t65", "t66", "t67", "t68", "t69", "t7", "t70", "t71",
"t72", "t73", "t74", "t75", "t76", "t77", "t78", "t79", "t8",
"t80", "t81", "t82", "t83", "t84", "t85", "t86", "t87", "t88",
"t89", "t9", "t90", "t91", "t92", "t93", "t94", "t95", "t96",
"t97", "t98", "t99"), class = "factor")), .Names = c("A", "T", "X", "Y", "V", "GD", "ND", "ND2", "TID"), row.names = c(NA, 6L),
class = "data.frame")
Your function is not vectorized. Try this:
theta <- function(x,Y) apply(Y,1,function(y,x) acos( sum(x*y) / ( sqrt(sum(x^2)) * sqrt(sum(y^2)) ) ),x=x)
a<-c(503,391)
b <- DF[, c("X","Y")]
theta(a,b)
# 1 2 3 4 5 6
#0.6412264 0.6412264 0.6412264 0.6412264 0.6412264 0.6412264
There is a problem with the acos and atan functions in this application, as you cannot compute angles for the full circle, only for the plus quadrant. In 2D, you need two values to specify a vector, and you need two values (sin and cos) to define it in degrees/radians up to 2pi. Here is an example of the acos problem:
plot(seq(1,10,pi/20)) ## A sequence of numbers
plot(cos(seq(1,10,pi/20))) ## Their cosines
plot(acos(cos(seq(1,10,pi/20)))) ## NOT Back to the original sequence
Here's an idea:
angle <- circular::coord2rad(x, y)
plot(angle)
where "(x,y)" has "angle"
as.numeric(angle)
gives the angle in radians (0,360). To report geographical directions, convert to degrees, and other things, you can use the added parameters for the circular function, e.g.:
x <- coord2rad(ea,eo, control.circular = list(type = "directions",units = "degrees"))
plot(x)
as.numeric(x)

Resources