plot 3D surface with R - r

I am having a problem ploting my data as a 3D surface using this script:
wireframe(Z~X*Y, data=FI02, xlab="X", ylab="Y", main="Surface elevation", drape=TRUE,
colorkey=TRUE, screen=list(z=-60, x=-60))
The output is just a cube without data / surface (see attachment). What was my mistake?
"X" "Y" "Z" "Plot"
552032.707 413894.885 10.8 2
552033.707 413896.585 13.4 2
552036.907 413899.685 18.5 2
552039.307 413898.085 10.5 2
552039.807 413894.585 11.2 2
552044.107 413894.985 9 2
552044.007 413895.035 11.5 2
552043.607 413896.985 13.4 2
552047.407 413897.885 8.2 2
552045.207 413898.985 10.7 2
552042.307 413902.085 9.4 2
552040.907 413902.885 12.5 2
552036.607 413901.585 11.4 2
552036.207 413901.435 12.4 2
552039.907 413905.285 18 2
552036.707 413906.585 9.7 2
552037.407 413908.785 6.3 2
552038.907 413911.085 7.5 2
552039.607 413911.285 16.8 2
552041.107 413908.985 9.5 2
552041.307 413910.385 14.5 2
552042.207 413909.985 9.3 2
552050.707 413911.985 12.5 2
552048.907 413909.985 18.6 2
552044.507 413906.585 6.7 2
552047.807 413904.085 6.8 2
552048.007 413904.285 12.8 2
552050.407 413903.885 9.7 2
552049.107 413909.785 5.2 2
552050.507 413910.785 12.5 2
552052.407 413908.685 16.5 2
552057.907 413910.385 10.3 2
552058.707 413909.785 18.5 2
552058.907 413910.485 12.4 2
552059.707 413908.385 15.3 2
552060.307 413910.785 7.2 2
552061.207 413911.985 11.8 2
552071.007 413912.185 17 2
552068.707 413911.385 8.3 2
552069.107 413910.885 15.5 2
552068.607 413908.485 8 2

Try this to see why I don't think this data is well suited for wireframe:
cloud(Z~X+Y, data=FI02, xlab="X", ylab="Y", main="Surface elevation",
type="l", screen=list(z=-60, x=-60))

Related

Adding numbers with condition R

I have the following data where e_in is exogenous giving. Ann then is an equal distribution of e_in, however, e_in can only be distributed downwards, i.e. a string (this is why 7 and 8 has ann=9 while 1 to 6 have ann=8.5)
e_in<-c(13,10,4,9,14,1,11,7)
ann<-c(8.5,8.5,8.5,8.5,8.5,8.5,9,9)
Dat_1<-data.frame(e_in,ann)
>Dat_1
e_in ann
1 13 8.5
2 10 8.5
3 4 8.5
4 9 8.5
5 14 8.5
6 1 8.5
7 11 9.0
8 7 9.0
I would now like to calculate how much e_in is available at each point down the string (shown as smn). So for 1 there is 13 e_in avabile, where 1 will take 8.5. Number 2 will then have own e_in + whatever is send downwards form 1 (here 10 + (13-8.5) = 14.5) and so on.
As the following:
smn<-c(13,14.5,10,10.5,16,8.5,11,9)
Dat_2<-data.frame(e_in,ann,smn)
>Dat_2
e_in ann smn
1 13 8.5 13.0
2 10 8.5 14.5
3 4 8.5 10.0
4 9 8.5 10.5
5 14 8.5 16.0
6 1 8.5 8.5
7 11 9.0 11.0
8 7 9.0 9.0
Is there any easy way/package for this sort of calculation
(I have done it ‘by hand’ for this example but it becomes significantly more time consuming with bigger strings.)
I think you just need the cumulative sum ofe_in minus the lagged cumulative sum of ann
Dat_1$smn <- cumsum(Dat_1$e_in) - cumsum(c(0, head(Dat_1$ann, -1)))
Dat_1
# e_in ann smn
# 1 13 8.5 13.0
# 2 10 8.5 14.5
# 3 4 8.5 10.0
# 4 9 8.5 10.5
# 5 14 8.5 16.0
# 6 1 8.5 8.5
# 7 11 9.0 11.0
# 8 7 9.0 9.0
I tried to think of a lag & window solution but couldn't so curious to see if anyone else managed it.
In place of that here's a loop that can do it:
Dat_1['smn'] = c(Dat_1[1, 'e_in'])
for (i in 2:nrow(Dat_1)){
Dat_1[i, 'smn'] <- Dat_1[i, 'e_in'] + Dat_1[i-1, 'smn'] - Dat_1[i-1, 'ann']
}
e_in ann smn
1 13 8.5 13.0
2 10 8.5 14.5
3 4 8.5 10.0
4 9 8.5 10.5
5 14 8.5 16.0
6 1 8.5 8.5
7 11 9.0 11.0
8 7 9.0 9.0
EDIT
Just seen Allan Cameron's answer which inspired me to correct it using dplyr
Dat_1 %>%
mutate(
smn = cumsum(e_in) - cumsum(lag(ann, n = 1L, default = 0))
)
Same result

boxplot doesn't show all the parameter in R

I write this code to execute an ANOVA for a simple dataframe and I want to draw a boxplot out of it
DF <- read.table('chromium.txt',header=TRUE)
Chromium.aov <- aov(Concentration ~ Lab,data=DF)
print(summary(Chromium.aov))
with(DF,boxplot(Concentration,Lab))
here is the text file
Lab Concentration
1 26.1
1 21.5
1 22.0
1 22.6
1 24.9
1 22.6
1 23.8
1 23.2
2 18.3
2 19.7
2 18.0
2 17.4
2 22.6
2 11.6
2 11.0
2 15.7
3 19.1
3 13.9
3 15.7
3 18.6
3 19.1
3 16.8
3 25.5
3 19.7
4 30.7
However, R only show 2 box plots for lab 1 and 2, not 3 and 4, how can I fix this?
boxplot(DF$Concentration ~ DF$Lab)
The syntax you used is making one box with all the values of 'Concentration', and another with the values of 'Lab'
When you do with(DF,boxplot(Concentration,Lab)), you are providing two sets of values to be plotted - Concentration and lab. You want to split the Concentration based on the unique values Lab and then create the boxplot.
boxplot(split(DF$Concentration, DF$Lab))

Wrong Fit using nls function

When I try to fit an exponential decay and my x axis has decimal number, the fit is never correct. Here's my data below:
exp.decay = data.frame(time,counts)
time counts
1 0.4 4458
2 0.6 2446
3 0.8 1327
4 1.0 814
5 1.2 549
6 1.4 401
7 1.6 266
8 1.8 182
9 2.0 140
10 2.2 109
11 2.4 83
12 2.6 78
13 2.8 57
14 3.0 50
15 3.2 31
16 3.4 22
17 3.6 23
18 3.8 20
19 4.0 19
20 4.2 9
21 4.4 7
22 4.6 4
23 4.8 6
24 5.0 4
25 5.2 6
26 5.4 2
27 5.6 7
28 5.8 2
29 6.0 0
30 6.2 3
31 6.4 1
32 6.6 1
33 6.8 2
34 7.0 1
35 7.2 2
36 7.4 1
37 7.6 1
38 7.8 0
39 8.0 0
40 8.2 0
41 8.4 0
42 8.6 1
43 8.8 0
44 9.0 0
45 9.2 0
46 9.4 1
47 9.6 0
48 9.8 0
49 10.0 1
fit.one.exp <- nls(counts ~ A*exp(-k*time),data=exp.decay, start=c(A=max(counts),k=0.1))
plot(exp.decay, col='darkblue',xlab = 'Track Duration (seconds)',ylab = 'Number of Particles', main = 'Exponential Fit')
lines(predict(fit.one.exp), col = 'red', lty=2, lwd=2)
I always get this weird fit. Seems to me that the fit is not recognizing the right x axis, because when I use a different set of data, with only integers in the x axis (time) the fit works! I don't understand why it's different with different units.
You need one small modification:
lines(predict(fit.one.exp), col = 'red', lty=2, lwd=2)
should be
lines(exp.decay$time, predict(fit.one.exp), col = 'red', lty=2, lwd=2)
This way you make sure to plot against the desired values on your abscissa.
I tested it like this:
data = read.csv('exp_fit_r.csv')
A0 <- max(data$count)
k0 <- 0.1
fit <- nls(data$count ~ A*exp(-k*data$time), start=list(A=A0, k=k0), data=data)
plot(data)
lines(data$time, predict(fit), col='red')
which gives me the following output:
As you can see, the fit describes the actual data very well, it was just a matter of plotting against the correct abscissa values.

How to change a column classed as NULL to class integer?

So I'm starting with a dataframe called max.mins that has 153 rows.
day Tx Hx Tn
1 1 10.0 7.83 2.1
2 2 7.7 6.19 2.5
3 3 7.1 4.86 0.0
4 4 9.8 7.37 2.7
5 5 13.4 12.68 0.4
6 6 17.5 17.47 3.5
7 7 16.5 15.58 6.5
8 8 21.5 20.30 6.2
9 9 21.7 21.41 9.7
10 10 24.4 28.18 8.0
I'm applying these statements to the dataframe to look for specific criteria
temp_warnings <- subset(max.mins, Tx >= 32 & Tn >=20)
humidex_warnings <- subset(max.mins, Hx >= 40)
Now when I open up humidex_warnings for example I have this dataframe
row.names day Tx Hx Tn
1 41 10 31.1 40.51 20.7
2 56 25 33.4 42.53 19.6
3 72 11 34.1 40.78 18.1
4 73 12 33.8 40.18 18.8
5 74 13 34.1 41.10 22.4
6 79 18 30.3 41.57 22.5
7 94 2 31.4 40.81 20.3
8 96 4 30.7 40.39 20.2
The next step is to search for 2 or 3 consective numbers in the column row.names and give me a total of how many times this occurs (I asked this in a previous question and have a function that should work once this problem is sorted out). The issue is that row.names is class NULL which is preventing me from applying further functions to this dataframe.
Help? :)
Thanks in advance,
Nick
If you need the row.names as a data as integer:
humidex_warnings$seq <- as.integer(row.names(humidex_warnings))
If you don't need row.names
row.names(humidex_warnings) <- NULL

similar to excel vlookup

Hi
i have a 10 year, 5 minutes resolution data set of dust concentration
and i have seperetly a 15 year data set with a day resolution of the synoptic clasification
how can i combine these two datasets they are not the same length or resolution
here is a sample of the data
> head(synoptic)
date synoptic
1 01/01/1995 8
2 02/01/1995 7
3 03/01/1995 7
4 04/01/1995 20
5 05/01/1995 1
6 06/01/1995 1
>
head(beit.shemesh)
X........................ StWd SHT PRE GSR RH Temp WD WS PM10 CO O3
1 NA 64 19.8 0 -2.9 37 15.2 61 2.2 241 0.9 40.6
2 NA 37 20.1 0 1.1 38 15.2 344 2.1 241 0.9 40.3
3 NA 36 20.2 0 0.7 39 15.1 32 1.9 241 0.9 39.4
4 NA 52 20.1 0 0.9 40 14.9 20 2.1 241 0.9 38.7
5 NA 42 19.0 0 0.9 40 14.6 11 2.0 241 0.9 38.7
6 NA 75 19.9 0 0.2 40 14.5 341 1.3 241 0.9 39.1
No2 Nox No SO2 date
1 1.4 2.9 1.5 1.6 31/12/2000 24:00
2 1.7 3.1 1.4 0.9 01/01/2001 00:05
3 2.1 3.5 1.4 1.2 01/01/2001 00:10
4 2.7 4.2 1.5 1.3 01/01/2001 00:15
5 2.3 3.8 1.5 1.4 01/01/2001 00:20
6 2.8 4.3 1.5 1.3 01/01/2001 00:25
any idea's
Make an extra column for calculating the dates, and then merge. To do this, you have to generate a variable in each dataframe bearing the same name, hence you first need some renaming. Also make sure that the merge column you use has the same type in both dataframes :
beit.shemesh$datetime <- beit.shemesh$date
beit.shemesh$date <- as.Date(beith.shemesh$datetime,format="%d/%m/%Y")
synoptic$date <- as.Date(synoptic$date,format="%d/%m/%Y")
merge(synoptic, beit.shemesh,by="date",all.y=TRUE)
Using all.y=TRUE keeps the beit.shemesh dataset intact. If you also want empty rows for all non-matching rows in synoptic, you could use all=TRUE instead.

Resources