2016-05-31 3 views
-2

Данные ужасно сформированы, но я ничего не могу сделать с источником. Я пытаюсь сортировать/форматировать его лучше, чтобы я мог выполнять анализ данных.Сортировка кадра данных с несколькими столбцами даты

В моем наборе данных есть несколько столбцов даты, начинающихся с разных дат начала. Вот пример:

DF <- data.frame(V1 = c('FS', 'Date', '1/31/2000','2/29/2000','',''), 
       V1.1 = c('','','99.87','99.97','',''), 
       V10 = c('FIIB','Date','10/29/2004','10/30/2004','12/31/2004','1/31/2005'), 
       V10.1 = c('','','103.24','104.82','105.14','107.68')) 

Это выглядит, как показано ниже, но с сотнями более столбцов:

  V1 V1.1  V10 V10.1 
1  FS    FIIB  
2  Date    Date  
3 1/31/2000 99.87 10/29/2004 103.24 
4 2/29/2000 99.97 11/30/2004 104.82 
5     12/31/2004 105.14 
6     1/31/2005 107.68 

дата начала фиксирована, что является 1/31/2000, и дата окончания является конец предыдущего месяца, который в этом случае составляет 4/30/2016. Дата окончания будет обновляться из месяца в месяц. Если в течение нескольких месяцев безопасность не возвращается, используйте пробел или NA. Например, поскольку FS имеет только цены на 1/31 и 2/29/2000, остальные (с 3/31/2000 по 4/30/2016) будут заготовками или НО. При этом, как говорится, данные должны выглядеть следующим образом:

V1   V2  V3  V4 
Date  FS  FIIB ...  
1/31/2000 99.87 NA  ... 
2/29/2000 99.97 NA  ... 
...  ... ... ... 
10/29/2004 NA  103.24 ... 
11/30/2004 NA  104.82 ... 
12/31/2004 NA  105.14 ... 
1/31/2005 NA  107.68 ... 
...  ... ... ... 
4/30/2016 ... ... ... 

Я знаю, как использовать order для сортировки данных на основе определенного столбца. Но с несколькими датами мне нужна помощь. Спасибо!

+0

Являются 'FS',' FIIB' и значения 'Date' должны быть переменными именами? Какова логика того, как они перемещаются между вашим примером и желаемым результатом? – effel

+0

Что вы на самом деле хотите сделать? «Очистить и упорядочить свой набор данных» довольно неопределенно ... – nsheff

+0

Да, «FS» и «FIIB» являются именами переменных (безопасности). Как вы можете видеть, каждая безопасность имеет месячные даты ниже и ежемесячную цену в следующем столбце. Проблема заключается в том, что даты начала отличаются между ценными бумагами. Например, 'FS' имеет данные о ценах на 1/31 и 2/29/2000, тогда как' FIIB' имеет данные с 10/29/2004 по 4/30/2016. Я хочу создать столбец «date» и соответствующим образом разместить месячные данные. –

ответ

2

Вы можете очистить это очень плохо отформатированный набор данных следующим образом:

# convert the columns to character values 
# this is only needed if they are stored as factor variables 
# alternatively you can read the dataframe with 'stringsAsFactors = FALSE' 
DF[] <- lapply(DF, as.character) 
# replace the empty spots with NA's 
DF[DF==''] <- NA 

# extract the first two columns into a new dataframe 
DF1 <- DF[complete.cases(DF[,1:2]), 1:2] 
# assign the correct names 
names(DF1) <- c(DF[2,1],DF[1,1]) 

# extract the next two columns into a new dataframe 
DF2 <- DF[complete.cases(DF[,3:4]), 3:4] 
# assign the correct names 
names(DF2) <- c(DF[2,3],DF[1,3]) 

# merge them into a new dataframe 
DFnew <- merge(DF1, DF2, by = 'Date', all = TRUE) 

, который дает:

> DFnew 
     Date FS FIIB 
1 1/31/2000 99.87 <NA> 
2 2/29/2000 99.97 <NA> 
3 10/29/2004 <NA> 103.24 
4 10/30/2004 <NA> 104.82 
5 12/31/2004 <NA> 105.14 
6 1/31/2005 <NA> 107.68 

Если у вас есть много столбцов организованы так же, как и в оригинале dataframe, довольно громоздко набирать все комбинации. Для этого случая можно обработать плохо отформатированный dataframe следующим образом (преобразование в символьные значения и замена пустого места остается неизменной):

# split the badly formatted dataframe into a list of dataframes 
lst1 <- lapply(seq(2,ncol(DF),2), function(i) DF[complete.cases(DF[,(i-1):i]), (i-1):i]) 

# set the names for each dataframe in the list 
lst2 <- lapply(seq(lst1), function(x) {names(lst1[[x]]) <- c(DF[2,(x*2-1)],DF[1,(x*2-1)]); return(lst1[[x]])}) 

# merge the list of dataframes back into one new dataframe 
DFnew <- Reduce(function(...) merge(..., by = 'Date', all = TRUE), lst2) 

, который дает:

> DFnew 
     Date FS FIIB 
1 1/31/2000 99.87 <NA> 
2 1/31/2005 <NA> 107.68 
3 10/29/2004 <NA> 103.24 
4 10/30/2004 <NA> 104.82 
5 12/31/2004 <NA> 105.14 
6 2/29/2000 99.97 <NA> 

Как вы можете видеть , это дает тот же результат (хотя и в другом порядке). Этот подход предполагает, что остальная часть вашего плохо отформатированного фрейма данных имеет ту же структуру, что и ваш примерный фреймворк.


Наконец, чтобы получить все в правильных классах и заказать новый dataframe согласно Date:

# set column classes 
DFnew[] <- lapply(DFnew, type.convert) 
# change the 'Date'-column to date-format 
DFnew$Date <- as.Date(DFnew$Date, format = '%m/%d/%Y') 
# set the order 
DFnew <- DFnew[order(DFnew$Date),] 

, который дает:

> DFnew 
     Date FS FIIB 
1 2000-01-31 99.87  NA 
6 2000-02-29 99.97  NA 
3 2004-10-29 NA 103.24 
4 2004-10-30 NA 104.82 
5 2004-12-31 NA 105.14 
2 2005-01-31 NA 107.68 
+0

Да, формат данных ужасен, и я ничего не могу сделать с источником. Вот почему я ищу способ лучше форматировать результаты. Благодарим вас за руководство. –

+0

Я просто делал эксперименты над своим набором данных. У меня более 100 столбцов, похожих на это. Есть ли лучший способ извлечь столбцы вместо использования 1: 2, 3: 4 и так далее? Спасибо! –

+0

@ T-T См. Обновление, HTH. – Jaap

Смежные вопросы