How to split a list to only use one column - r

I'm relatively new to R, and I can't figure out how to split the list that I'm working with. I have
B<-tapply(newdata$lf.d1, newdata$year, mean)
But I want to concatenate the mean values onto another matrix without the year values. How would I go about doing this?

The result of tapply with a single grouping factor will be an R contingency table with rownames. There is only a single column (actually not even that because it is a table object and only has a single dimension unless you coerce it with as.matrix). If you want to remove the names, then use the unname function.
unname(B)
unname(as.matrix(B))

Related

improving specific code efficiency - *base R* alternative to for() loop solution

Looking for a vectorized base R solution for my own edification. I'm assigning a value to a column in a data frame based on a value in another column in the data frame.
My solution creates a named vector of possible codes, looks up the code in the original column, subsets the named list by the value found, and assigns the resulting name to the new column. I'm sure there's a way to do exactly this using the named vector I created that doesn't need a for loop; is it some version of apply?
dplyr is great and useful and I'm not looking for a solution that uses it.
# reference vector for assigning more readable text to this table
tempAssessmentCodes <- setNames(c(600,301,302,601,303,304,602,305,306,603,307,308,604,309,310,605,311,312,606,699),
c("base","3m","6m","6m","9m","12m","12m","15m","18m","18m","21m","24m","24m","27m","30m","30m",
"33m","36m","36m","disch"))
for(i in 1:nrow(rawDisp)){
rawDisp$assessText[i] <- names(tempAssessmentCodes)[tempAssessmentCodes==rawDisp$assessment[i]]
}
The standard way is to use match():
rawDisp$assessText <- names(tempAssessmentCodes)[match(rawDisp$assessment, tempAssessmentCodes)]
For each y element match(x, y) will find a corresponding element index in x. Then we use the names of y for replacing values with names.
Personally, I do it the opposite way - make tempAssesmentCodes have names that correspond to old codes, and values correspond to new codes:
codes <- setNames(names(tempAssessmentCodes), tempAssessmentCodes)
Then simply select elements from the new codes using the names (old codes):
rawDisp$assessText <- codes[as.character(rawDisp$assessment)]

How to reference a column in a dataframe through a variable in R

I'm trying to iterate through columns in an R data.frame.
To do so, I'm hoping to write a for loop which loops over the column names and then filters the data.table accordingly with values.
My issue is that given the syntax:
df[which(df$XX == y), ]
XX needs to actually be a column name versus a variable that is a string equivalent to the column name.
Is there a way to loop over the columns via inputting a variable?
Many thanks!

apply resulting in list instead of dataframe

I have a dataframe with cases that repeat on the rows. Some rows have more complete data than others. I would like to group cases and then assign the first non-missing value to all NA cells in that column for that group. This seems like a simple enough task but I'm stuck. I have working syntax but when I try to use apply to apply the code to all columns in the dataframe I get a list back instead of a dataframe. Using do.call(rbind) or rbindlist or unlist doesn't quite fix things either.
Here's the syntax.
df$groupid<-group_indices (df,id1,id2) #creates group id on the basis of a combination of two variables
df%<>%group_by(id1,id2) #actually groups the dataframe according to these variables
df<-summarise(df, xvar1=xvar1[which(!is.na(xvar1))[1]]) #this code works great to assign the first non missing value to all missing values but it only works on 1 column at a time (X1).
I have many columns so I try using apply to make this a manageable task..
df<-apply(df, MARGIN=2, FUN=function(x) {summarise(df, x=x[which(!is.na(x))[1]])
}
)
This gets me a list for each variable, I wanted a dataframe (which I would then de-duplicate). I tried rbindlist and do.call(rbind) and these result in a long dataframe with only 3 columns - the two group_by variables and 'x'.
I know the problem is simply how I'm using apply, probably the indexing with 'which', but I'm stumped.
What about using lapply with do.call and cbind, like the following:
df <- do.call(cbind, lapply(df, function(x) {summarise(df, x=x[which(!is.na(x))[1]])}))

R matrix and data.frame mix-up

I have a data.frame in R with columns that also have column names.
I have another data.frame with 0s and -1s that controls which columns to use from the first data.frame in a subsequent analysis.
I now ran into an issue that I cannot wrap my head around.
First of all, the "offending" line of code is:
covar.data<-covar.data[,!onoff]
FYI I have confirmed both covar.data and onoff are data.frames.
When I run this with onoff selecting 2 or more columns, everything is fine, and the resulting covar.data is still a data.frame - and this is important, because I need to use the column names in the rest of my analysis.
However, if I have onoff selecting only 1 column, covar.data turns into a matrix!! This is a problem, because the column name also disappears!
I tried
covar.data<-as.data.frame(covar.data[,!onoff])
and
covar.data<-as.data.frame(covar.data[,!onoff], col.names=TRUE)
but that didn't make a difference in the disappearance of the column name.
I don't understand why R decides to turn the data.frame into a matrix (only for the times I am left with one column), and I cannot figure out how to preserve the data.frame PLUS the column names.
If you select a single column of a data.frame, R assumes you want to extract that data as a vector rather than returning another data.frame (and in most cases this is exactly the behavior you want). But if you do want to keep that single column as a data.frame, then you should do
covar.data[,!onoff, drop=F]

Change part of data frame to character, then to numeric in R

I have a simple problem. I have a data frame with 121 columns. columns 9:121 need to be numeric, but when imported into R, they are a mixture of numeric and integers and factors. Columns 1:8 need to remain characters.
I’ve seen some people use loops, and others use apply(). What do you think is the most elegant way of doing this?
Thanks very much,
Paul M
Try the following... The apply function allows you to loop over either rows, cols, or both, of a dataframe and apply any function, so to make sure all your columns from 9:121 are numeric, you can do the following:
table[,9:121] <- apply(table[,9:121],2, function(x) as.numeric(as.character(x)))
table[,1:8] <- apply(table[,1:8], 2, as.character)
Where table is the dataframe you read into R.
Briefly I specify in the apply function the table I want to loop over - in this case the subset of your table we want to make changes to, then we specify the number 2 to indicate columns, and finally give the name of the as.numeric or as.character functions. The assignment operator then replaces the old values in your table with the new ones of correct format.
-EDIT: Just changed the first line as I recalled that if you convert from a factor to a number, what you get is the integer of the factor level and not the number you think you are getting to factors first need to be converted to characters, then numbers, which was can do just by wrapping as.character inside as.numeric.
When you read in the table use strinsAsFactors=FALSE then there will not be any factors.

Resources