user user -4 years ago 144
R Question

split dataframe using common rows dynamically

I have a dataframe is called data:

**Select.Actions** **Current.State** **Next.State**
Hire new staff Out of Benchmark Withinbenchmark
Hire new staff Out of Benchmark Withinbenchmark
Discuss with Customer Withinbenchmark Withinbenchmark
Discuss with Customer Withinbenchmark Withinbenchmark
Discuss with Customer Out of Benchmark Out of Benchmark
Fire new staff Out of Benchmark Withinbenchmark
Discuss with Customer Withinbenchmark Withinbenchmark
Discuss with Customer Out of Benchmark Withinbenchmark
Fire new staff Out of Benchmark Withinbenchmar


I want to have separate data frame based on the values of Select.Actions.

#select First Column of dataframe
d<-data[1]


Then I want to match data with the input of d. Because d is dynamic and it will change over time so I wrote a loop to split data frame to different dataframe:

split<-for(i in 1:length(d)){
z[i]<-subset(data, data[,"Select.Actions"] %in% d[i],select=c(Current.State,Next.State))}


Then I got the following warning message.

Warning message:
In `[<-.data.frame`(`*tmp*`, i, value = list(Current.State = integer(0), :
provided 2 variables to replace 1 variables


Could you please advise me in terms of logic?

and the output is NULL.

Answer Source

You are assigning multiple rows and columns in z[i]<-subset(data, ..., you can use rbind. I'd suggest not using subset as explained by Hadely here. Let me know if dplyr solution below works for you.

library(dplyr)
data <- read.table(text = 'Select.Actions,Current.State,Next.State
Hire new staff,Out of Benchmark,Withinbenchmark
Hire new staff,Out of Benchmark,Withinbenchmark
Discuss with Customer,Withinbenchmark,Withinbenchmark
Discuss with Customer,Withinbenchmark,Withinbenchmark
Discuss with Customer,Out of Benchmark,Out of Benchmark
Fire new staff,Out of Benchmark,Withinbenchmark
Discuss with Customer,Withinbenchmark,Withinbenchmark
Discuss with Customer,Out of Benchmark,Withinbenchmark
Fire new staff, Out of Benchmark,Withinbenchmar', 
                   header = TRUE, sep =",", stringsAsFactors = FALSE)



z <- NULL
for(i in 1:nrow(data))
{
  interm_data <- data %>% filter(Select.Actions == data[i,1]) %>% select(Current.State, Next.State) 
  if(is.null(z))
  {
    z<- interm_data
  }else{
    z<- rbind(z,interm_data)
  }
  print(data[i,1])
  print(interm_data)

}

**Updated **

Based on user's comments.

z <- list()
trim <- function (x) gsub("^\\s+|\\s+$", "", x)
for(i in unique(data$Select.Actions))
{
  z[[trim(i)]] <- data %>% filter(Select.Actions == i) %>% select(Current.State, Next.State) 
}
list2env(z ,.GlobalEnv)
# Now you will have 3 data sets `Hire new staff`, `Fire new staff` and `Discuss with customer` in your workspace.

However, I'd not use the loop in the first place for your needs.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download