R function with multiple operators - r

data ranges from -6 to 6 and I am trying to create 3 categories, however my function is not returning anyone for category 2 even though there are people present
FFMIBMDcopdcases$lowBMD = ifelse((FFMIBMDcopdcases$copd_Tscore >= -1) , 0,
ifelse((FFMIBMDcopdcases$copd_Tscore < -1), 1,
ifelse((FFMIBMDcopdcases$copd_Tscore <= -2.5), 2, NA)))

Try using cut function. Example:
myValues <- runif(n = 20, min = -6, max = 6)
as.numeric(as.character(cut(x = myValues, breaks = c(-Inf, -2.5, -1, Inf), labels = c(2, 1, 0))))

Since you want a numeric result it might be easiest to use findInterval although you will need to subtract the result from 2 to get in the inverse order ( 2 for lowest and 0 for highest) :
FFMIBMDcopdcases$lowBMD = 2 - findInterval(FFMIBMDcopdcases$copd_Tscore ,
c(-Inf, -2.5, -1, Inf) )

Related

Problem with radarchart using fmbs library

I'm helping a friend making figures to her publication. She need radar charts, send me the data. I'm using fmsb library in R, but have some problem. The data is the following (some modified, because it's unpublished :) )
consequences
timeline
personal control
treatment
control
identity
concern
comprehensibility
emotions
Min
0
0
0
0
0
0
0
0
Max
10
10
10
10
10
10
10
10
Mean
7.74
6.14
5.2
2.82
7.12
7.18
2.44
7.26
The code:
radarchart(chaos_story2,
axistype = 4,
axislabcol = "black",
seg = 5,
caxislabels= c(0,2,4,6,8,10),
cglcol="black")
The problem, that it seems the radarchart use the 1-mean values to plot the means, not the actual values. How I can solve this?
Thank you in advance
The issue is that the min and max rows are in the wrong order. According to the docs ?radarchart:
If maxmin is TRUE, this must include maximum values as row 1 and minimum values as row 2 for each variables, and actual data should be given as row 3 and lower rows.
Fixing the order gives the desired result.
Note: There is probably an issue with your example data, i.e. I dropped the consequences column as it contained the rownames.
library(fmsb)
# Max has to be first row, min the second
chaos_story2 <- chaos_story2[c(2, 1, 3), ]
radarchart(chaos_story2,
axistype = 4,
axislabcol = "black",
seg = 5,
caxislabels= c(0,2,4,6,8,10),
cglcol="black")
DATA
chaos_story2 <- data.frame(
consequences = c("Min", "Max", "Mean"),
timeline = c(0, 10, 7.74),
personal.control = c(0, 10, 6.14),
treatment = c(0, 10, 5.2),
control = c(0, 10, 2.82),
identity = c(0, 10, 7.12),
concern = c(0, 10, 7.18),
comprehensibility = c(0, 10, 2.44),
emotions = c(0, 10, 7.26)
)
rownames(chaos_story2) <- chaos_story2$consequences
chaos_story2$consequences <- NULL
``

judge the values crossing zero

I would like to determine whether or not the ranges of min and max values cross zero (0 = crossing zero, 1 = not crossing zero).
min <- c(0, -1, -1, 1, 1)
max <- c(1, 1, -0.1, 3, 1.5)
answer <- c(0, 0, 1, 1, 1)
data <- cbind(min,max, answer)
You can use the between function from dplyr:
library(dplyr)
min <- c(0, -1, -1, 1, 1)
max <- c(1, 1, -0.1, 3, 1.5)
df1 = data.frame(min,max) %>%
rowwise() %>%
mutate(answer = as.numeric(!between(0,min,max)))
Or using base R:
df1 = data.frame(min,max)
df1$answer = apply(df1, 1, function(x) as.numeric(!(x[1]<= 0 & x[2] >=0)))
Base R vectorised answer -
transform(data, answer = as.integer(!(min <= 0 & max > 0)))
# min max answer
#1 0 1.0 0
#2 -1 1.0 0
#3 -1 -0.1 1
#4 1 3.0 1
#5 1 1.5 1
If you prefer dplyr the same can be written as -
library(dplyr)
data %>% mutate(answer = as.integer(!(min <= 0 & max > 0)))
data
min <- c(0, -1, -1, 1, 1)
max <- c(1, 1, -0.1, 3, 1.5)
data <- data.frame(min,max)
You can simply multiply them, as to cross you either need a negative product or one being zero.
answer <- ifelse(min * max <= 0, 0, 1)
or
answer <- as.integer(min * max > 0)
# [1] 0 0 1 1 1
If your 0 and 1 are not a requirement, even shorter to get a TRUE or FALSE
answer <- min * max <= 0
# [1] TRUE TRUE FALSE FALSE FALSE

Calculate row specific based on min

My data looks like this
df <- data.frame(x = c(3, 5, 4, 4, 3, 2),
y = c(.9, .8, 1, 1.2, .5, .1))
I am trying to multiply each x value by either y or 1, depending on which has the least value.
df$z <- df$x * min(df$y, 1)
The problem is it is taking the min of the whole column, so it is multiplying every x by 0.1.
Instead, I need x multiplied by .9, .8, 1, 1, .5, .1...
We need pmin that will go through each value of 'y' and get the minimum val when it is compared with the second value (which is recycled)
pmin(df$y, 1)
#[1] 0.9 0.8 1.0 1.0 0.5 0.1
Likewise, we can have n arguments (as the parameter is ...)
pmin(df$y, 1, 0)
#[1] 0 0 0 0 0 0
To get the output, just multiply 'x' with the pmin output
df$x * pmin(df$y, 1)
which can also be written as
with(df, x * pmin(y, 1))
Maybe you could use an ifelse function:
df <- data.frame(x = c(3, 5, 4, 4, 3, 2),
y = c(.9, .8, 1, 1.2, .5, .1))
df$z = ifelse(df$y<1, df$x*df$y, df$x*1)
This will compare the values of each row.
Hope it helps! :)

Assigning NAs to values in a list

I have a data frame that includes many variables. Here is a shortened version of what I have so far:
n_20010_0_0 <- c(1,2,3,4)
n_20010_0_1 <- c(0, -2, NA, 4)
n_20010_0_2 <- c(3, 0, -7, 2)
x <- data.frame (n_20010_0_0, n_20010_0_1, n_20010_0_2)
I created a new variable that returns whether or not there is a 1 within the list of variables:
MotherIllness0 <- paste("n_20010_0_", 0:2, sep = "")
x$MotherCAD_0_0 <- apply(x, 1, function(x) as.integer(any(x[MotherIllness0] == 1, na.rm = TRUE)))
I would like to keep the NAs as 0's, but I would also like to recode it so that if there is a -7 the new value is NA.
This is what I've tried and it doesn't work:
x$MotherCAD_0_0[MotherIllness0 == -7] <- NA
you don't need to define MotherIllness0, the argument 1 in your apply function takes care of that.
Here's a line of code that does both things you want.
MotherIllness0 <- paste("n_20010_0_", 0:2, sep = "")
x$MotherCAD_0_0<- apply(x[,MotherIllness0], 1, function(x) ifelse(any(x==-7), NA,
as.integer(any(x==1, na.rm=T))))
I assumed that a row with both 1s and -7s should have NA for the new variable. If not, then this should work:
x$MotherCAD_0_0<- apply(x[,MotherIllness0], 1, function(x) ifelse(any(x==1, na.rm=T), 1,
ifelse(any(x==-7), NA, 0)))
Note that with the example you have above, these two lines should produce the same outcome.
Here's another way to do it, without using any if-else logic:
# Here's your dataset, with a row including both 1 and -7 added:
x <- data.frame (n_20010_0_0 = c(1, 2, 3, 4, 1),
n_20010_0_1 = c(0, -2, NA, 4, 0) ,
n_20010_0_2 = c(3, 0, -7, 2, -7)
)
# Your original function:
MotherIllness0 <- paste("n_20010_0_", 0:2, sep = "")
x$MotherCAD_0_0 <- apply(x, MARGIN = 1, FUN = function(x) {
as.integer(
any(x[MotherIllness0] == 1, na.rm = TRUE)
)
})
# A simplified version
x$test <- apply(x, MARGIN = 1, FUN = function(row) {
as.integer(
any(row[MotherIllness0] == 1, na.rm = TRUE) &
!any(row[MotherIllness0] == -7, na.rm = TRUE)
)
})
A couple of notes: the name of x in an anonymous function like function(x) can be anything, and you'll save yourself a lot of confusion by calling it what it is (I named it row above).
It's also unlikely that you actually need to convert your result column to integer - logical columns are easier to interpret, and they work the same as 0-1 columns for just about everything (e.g., TRUE + FALSE equals 1).

Conditional simulating based on matches and probability

Two matrices
df_A = matrix(, nrow = 5, ncol = 3)
df_A[,1] = c(0, 0, 1, -1, 1)
df_A[,2] = c(0, 1, -1, 0, -1)
df_A[,3] = c(1, 0, -1, 1, 1)
df_B = matrix(, nrow = 5, ncol = 3)
df_B[,1] = c(1, -1, 0, 0, 1)
I want to simulate columns 2 and 3 for df_B based on a few conditions. If the value of df_A is zero, the value for df_B does not change. For example, the first two values for df_B should not change for the first iteration because the first two values for df_A are zero. If the value of df_A is one or negative one, then the respective value for df_B will take on that value given a certain probability (20% in this example). For example, if df_A is negative one and df_B is zero (or one), the respective value for df_B will become negative one 20% of the time.
I know the following is incorrect but here is what I have so far:
belief_change = function(x){
if (df_A[x] = -1 & df_B[x] != -1 & sample(1:2, 1, prob = c(0.2, 0.8) = 1))
df_B[x+1] = df_A[x]
else
df_B[x+1] = df_B[x]
if (df_A[x] = 1 & df_B[x] != 1 & sample(1:2, 1, prob = c(0.2, 0.8) = 1))
df_B[x+1] = df_A[x]
else
df_B[x+1] = df_B[x]
if (df_A[x] = 0)
df_B[x+1] = df_B[x]
}
I'm using the sample function here to help generate a probability. I also need to put this into a for-loop eventually.
There are several errors in your code. First, the correct logical equality operator is == not =. Second, you put = 1 inside the call to sample. Third, if you really want to affect the environment outside where the function is called (i.e. to change df_B by calling your function, you need to use the deep assignment operator <<-, not = or <-. You can read more about this here.
Here is a version of your code that works; see if it does what you want it to do.
belief_change <- function(x) {
if (df_A[x] == -1 & df_B[x] != -1 & sample(1:2, 1, prob = c(0.2, 0.8)) == 1)
df_B[x+1] <<- df_A[x]
else
df_B[x+1] <<- df_B[x]
if (df_A[x] == 1 & df_B[x] != 1 & sample(1:2, 1, prob = c(0.2, 0.8)) == 1)
df_B[x+1] <<- df_A[x]
else
df_B[x+1] <<- df_B[x]
if (df_A[x] == 0)
df_B[x+1] <<- df_B[x]
}

Resources