R - создать и присвоить имена фреймам данных из существующих значений столбцов - PullRequest
0 голосов
/ 07 сентября 2018

У меня есть фрейм данных, который структурирован следующим образом: dput:

structure(list(railroad = c("bnsf railway company", "bnsf railway company", 
"bnsf railway company", "bnsf railway company", "bnsf railway company", 
"bnsf railway company", "bnsf railway company", "bnsf railway company", 
"union pacific railroad", "union pacific railroad", "union pacific railroad", 
"union pacific railroad", "union pacific railroad", "union pacific railroad", 
"union pacific railroad", "union pacific railroad"), measure = 
c("cars.owned.by", 
"cars.owned.by", "cars.type", "cars.type", "cars.type", "train.speed", 
"train.speed", "terminal.dwell", "cars.owned.by", "cars.owned.by", 
"cars.type", "cars.type", "cars.type", "train.speed", "train.speed", 
"terminal.dwell"), category = c("system", "private", "box", "intermodal", 
"total", "intermodal", "all.trains", "entire.railroad", "system", 
"private", "box", "intermodal", "total", "intermodal", "all.trains", 
"entire.railroad"), irm = c(201510L, 201510L, 201510L, 201510L, 
201510L, 201510L, 201510L, 201510L, 201510L, 201510L, 201510L, 
201510L, 201510L, 201510L, 201510L, 201510L), mean = c(66623, 
149937.333, 11395, 16499, 236866, 33.3, 24.5, 25.267, 57618.333, 
195764.667, 22229.333, 14135.333, 293164.333, 31.933, 26.6, 27.6
)), row.names = c(1L, 3L, 6L, 9L, 14L, 15L, 20L, 32L, 127L, 129L, 
132L, 135L, 140L, 141L, 146L, 160L), class = "data.frame")

Я хотел бы сделать следующее:

  1. Создание отдельных фреймов данных для каждой комбинации measure и category, именуется вставкой measure и category, разделенных ".". Таким образом, первый кадр данных будет называться cars.owned.by.system и т. Д.

  2. Переименуйте пятый столбец, mean каждого фрейма данных, в имя самого фрейма данных. Итак, для первого кадра данных это будет colnames(df)[5] <- cars.owned.by.system.

Желаемый вывод - 8 отдельных фреймов данных, названных как я уже говорил выше

Я попробовал следующее:

cars.owned.by.system <- df[df$category == "system",]
colnames(cars.owned.by.system)[5[ <- cars.owned.by.system

И это делает свою работу, но я не хочу делать это постоянно. Я полагаю, что существует вариант канонического подхода «разделяй и применяй», который бы работал. Любой совет или помощь будет высоко ценится. Благодарю.

Ответы [ 4 ]

0 голосов
/ 08 сентября 2018

Это даст вам именованный список фреймов данных, который почти наверняка предпочтительнее, чем иметь их все отдельно в вашей глобальной среде:

lst <- split(df, paste(df$measure, df$category, sep = ".")) %>% 
  purrr::imap(~`names<-`(.x, c(names(.x)[1:4], .y)))
0 голосов
/ 08 сентября 2018

А как насчет классического цикла for:

# first create the pasted name to iterate the loop 
df$name <- paste(df$railroad,df$measure,sep='.')

# an empty list to have all your df
list_df <- list()

# the loop
for (i in df$name){
data <- df[which(df$name == i),]  # select the df of name
colnames(data)[4]<-i              # rename the mean
data<- data[,-5]                  # remove the useless name
list_df[[i]] <- data              # store in list
}

# here you can see all the df in a list
list_df

> list_df
$`bnsf railway company.cars.owned.by`
              railroad       measure category bnsf railway company.cars.owned.by                               name
1 bnsf railway company cars.owned.by   system                             201510 bnsf railway company.cars.owned.by
3 bnsf railway company cars.owned.by  private                             201510 bnsf railway company.cars.owned.by

$`bnsf railway company.cars.type`
               railroad   measure   category bnsf railway company.cars.type                           name
6  bnsf railway company cars.type        box                         201510 bnsf railway company.cars.type
9  bnsf railway company cars.type intermodal                         201510 bnsf railway company.cars.type
14 bnsf railway company cars.type      total                         201510 bnsf railway company.cars.type
... and so on  

# you can select each df, for example choosin its name
list_df$`bnsf railway company.cars.type`
                    railroad   measure   category bnsf railway company.cars.type                           name
6  bnsf railway company cars.type        box                         201510 bnsf railway company.cars.type
9  bnsf railway company cars.type intermodal                         201510 bnsf railway company.cars.type
14 bnsf railway company cars.type      total                         201510 bnsf railway company.cars.type

# and you're sure it's a df
class(list_df$`bnsf railway company.cars.type`)
[1] "data.frame"
0 голосов
/ 08 сентября 2018

Рассмотрим split для подстановки фрейма данных двумя факторами, а затем Map (оболочка для mapply) для поэтапной итерации по поднастроенным фреймам данных и именам списка.

Также рассмотрим setNames() левую версию colnames() для возврата нового именованного объекта за один вызов.

# CREATES NAMED LIST
df_list <- split(df, list(df$measure, df$category))

# RETURNS SAME LIST WITH RENAMED FIFTH COLUMN
df_list <- Map(function(sub, nm) setNames(sub, c("railroad", "measure", "category", "irm", nm)), 
               df_list, names(df_list))

# OUTPUT DFs 
df_list$cars.owned.by.all.trains

df_list$cars.type.all.trains

df_list$terminal.dwell.all.trains 
...
0 голосов
/ 08 сентября 2018

Предполагая, что df - ваш фрейм данных, я думаю, что это делает.

for(cat in unique(df$category)) {
  newdf<-paste("cars.owned.by.", cat, sep="")
  assign(newdf, df[df$category==cat,])
  eval(parse(text=paste("colnames(", newdf, ")[5] <- '", newdf, "'", sep="")))
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...