2016-07-29 8 views
0

Как объединить векторы с различным числом или строками в кадре данных в R. Вот пример. Каждый вектор имеет 7 или 9 строк. sourceVersion и устройство являются дополнительными двумя строками. Я хочу, чтобы они были включены в кадр данных и оставлены пустыми или установлены в NA для 7-векторных наблюдений, как показано в приведенной ниже таблице.R Комбинированные векторы с разной длиной строки

Я хочу данные в кадре данных, как это.

type         sourceName    sourceVersion device                           unit creationDate startDate  endDate   value 
HKQuantityTypeIdentifierFlightsClimbed Ryan Praskievicz iPhone 9.3.2   <<HKDevice: 0x15a4af3f0>, name:iPhone, manufacturer:Apple, model:iPhone, hardware:iPhone8,1, software:9.3.2> count 6/2/2016 12:27 6/2/2016 12:09 6/2/2016 12:09 1 
HKQuantityTypeIdentifierStepCount  Ryan Praskievicz iPhone                                 count 10/2/2014 8:30 9/24/2014 15:07 9/24/2014 15:07 7 

Это то, что я пробовал.

library(XML) 

xmlstr <- '<?xml version="1.0" encoding="UTF-8"?> 
      <HealthData locale="en_US"> 
       <ExportDate value="2016-06-02 14:05:23 -0400"/> 
       <Me HKCharacteristicTypeIdentifierDateOfBirth="" HKCharacteristicTypeIdentifierBiologicalSex="HKBiologicalSexNotSet" HKCharacteristicTypeIdentifierBloodType="HKBloodTypeNotSet" HKCharacteristicTypeIdentifierFitzpatrickSkinType="HKFitzpatrickSkinTypeNotSet"/> 
       <Record type="HKQuantityTypeIdentifierStepCount" sourceName="Ryan Praskievicz iPhone" unit="count" creationDate="2014-10-02 08:30:17 -0400" startDate="2014-09-24 15:07:06 -0400" endDate="2014-09-24 15:07:11 -0400" value="7"/> <Record type="HKQuantityTypeIdentifierFlightsClimbed" sourceName="Ryan Praskievicz iPhone" sourceVersion="9.3.2" device="&lt;&lt;HKDevice: 0x15a4af3f0&gt;, name:iPhone, manufacturer:Apple, model:iPhone, hardware:iPhone8,1, software:9.3.2&gt;" unit="count" creationDate="2016-06-02 12:27:46 -0400" startDate="2016-06-02 12:09:29 -0400" endDate="2016-06-02 12:09:29 -0400" value="1"/> </HealthData>' 

xml <- xmlParse(xmlstr) 

recordAttribs <- xpathSApply(doc=xml, path="//HealthData/Record", xmlAttrs) 
df <- data.frame(t(recordAttribs)) 
df 

Это то, что я получаю для вывода на R консоли

 X1 
      1 HKQuantityTypeIdentifierStepCount, Ryan Praskievicz iPhone, count, 2014-10-02 08:30:17 -0400, 2014-09-24 15:07:06 -0400, 2014-09-24 15:07:11 -0400, 7                                                                     
    X2 
1 HKQuantityTypeIdentifierFlightsClimbed, Ryan Praskievicz iPhone, 9.3.2, <<HKDevice: 0x15a4af3f0>, name:iPhone, manufacturer:Apple, model:iPhone, hardware:iPhone8,1, software:9.3.2>, count, 2016-06-02 12:27:46 -0400, 2016-06-02 12:09:29 -0400, 2016-06-02 12:09:29 -0400, 1 
+0

Would [это] (http://webcache.googleusercontent.com/search?q=cache:lPRvnOOSAgoJ:www.inside-r.org/packages/ cran/qpcR/docs/cbind.na + & cd = 4 & hl = en & ct = clnk & gl = us) делают то, что вы ищете? –

+0

Прежде всего, вы пытаетесь связать строки с различным количеством столбцов, а не связывать столбцы с различным количеством строк. При этом, не так ли, в общем, проблема с выравниванием столбцов? То есть, если в одной строке меньше столбцов, чем другой, откуда вы знаете, какие столбцы отсутствуют, если вы не можете каким-то образом вывести это из данных? – aichao

+0

@aichao Кажется, что те же две строки отсутствуют - sourceVersion и устройство. – Warner

ответ

1

Вот способ сделать это с помощью sapply и lapply.

recordAttribs <- xpathSApply(doc=xml, path="//HealthData/Record", xmlAttrs) 

recordAttribs <- t(recordAttribs) 

Получить вектор TRUE/FALSE с использованием sapply на основе того, элементы в списке равны 7.

short.condition <- sapply(recordAttribs, function(x) length(x)==7) 

Использование lapply на подмножестве вашего списка, который удовлетворяет этому условию. На этот раз вы конкатенации два NA внутри векторов, которые удовлетворяют этому условию:

recordAttribs[short.condition] <- lapply(recordAttribs, 
             function(x) c(x[1:2],NA,NA,x[3:7])) 

Чтобы преобразовать это в data.frame в форме вы хотите:

df <- matrix(unlist(recordAttribs), 
      nrow=2,ncol=9, byrow=TRUE) 

df <- data.frame(df, stringsAsFactors=FALSE) 

names(df) <- c("type","sourceName","sourceVersion","device","unit","creationDate","startDate","endDate","value") 

который выглядит следующим образом:

> str(df) 
'data.frame': 2 obs. of 9 variables: 
$ type   : chr "HKQuantityTypeIdentifierStepCount" "HKQuantityTypeIdentifierFlightsClimbed" 
$ sourceName : chr "Ryan Praskievicz iPhone" "Ryan Praskievicz iPhone" 
$ sourceVersion: chr NA "9.3.2" 
$ device  : chr NA "<<HKDevice: 0x15a4af3f0>, name:iPhone, manufacturer:Apple, model:iPhone, hardware:iPhone8,1, software:9.3.2>" 
$ unit   : chr "count" "count" 
$ creationDate : chr "2014-10-02 08:30:17 -0400" "2016-06-02 12:27:46 -0400" 
$ startDate : chr "2014-09-24 15:07:06 -0400" "2016-06-02 12:09:29 -0400" 
$ endDate  : chr "2014-09-24 15:07:11 -0400" "2016-06-02 12:09:29 -0400" 
$ value  : chr "7" "1" 
+0

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

+0

@RyanPraskievicz Я отредактировал мой ответ на счет для этого. Это не самое приятное решение. Я предполагаю, что те же две колонки будут отсутствовать для ваших наблюдений с 7 строками. – Warner

+0

@ RyanPraskievicz сделал еще одно редактирование, чтобы вывести вывод в полезный файл data.frame. – Warner

2

зависимость немного эзотерическим, но вы можете сделать:

library(data.table) 
rbindlist(lapply(recordAttribs, function(x) data.table(t(x))), fill=TRUE) 

Это вернет data.table, который наследует data.frame.

         type    sourceName unit 
1:  HKQuantityTypeIdentifierStepCount Ryan Praskievicz iPhone count 
2: HKQuantityTypeIdentifierFlightsClimbed Ryan Praskievicz iPhone count 
       creationDate     startDate     endDate value 
1: 2014-10-02 08:30:17 -0400 2014-09-24 15:07:06 -0400 2014-09-24 15:07:11 -0400  7 
2: 2016-06-02 12:27:46 -0400 2016-06-02 12:09:29 -0400 2016-06-02 12:09:29 -0400  1 
    sourceVersion 
1:   NA 
2:   9.3.2 
                             device 
1:                           NA 
2: <<HKDevice: 0x15a4af3f0>, name:iPhone, manufacturer:Apple, model:iPhone, hardware:iPhone8,1, software:9.3.2> 

Причина я использую data.table в том, что он имеет смарт-rbind метод с use.names=TRUE вариант, который позволяет строки неравной длины, спичек столбцов на имя не позиции, и заполняет недостающие значения с НС.

Simpler пример того, как rbind.data.table работ:

d1 = data.table(a="foo", b = "bar", c = "baz") 
d2 = data.table(b="bar", a = "foo") 
rbind(d1, d2) # throws helpful error: "If instead you need to fill missing columns, use set argument 'fill' to TRUE." 
rbind(d1, d2, fill=TRUE) 
#  a b c 
# 1: foo bar baz 
# 2: foo bar NA 
+0

это отлично работает! Когда я пытаюсь запустить команду df <-do.call (rbind, c (lapply (recordAttribs, function (x) data.table (t (x))), fill = TRUE)) 'в моем полном наборе данных' recordAttribs' - это большой список (405677 элементов, 464 МБ), для его выполнения требуется много времени. Любые идеи о том, что делать, чтобы улучшить это с помощью большего набора данных? –

+0

@RyanPraskievicz, пожалуйста, попробуйте 'rbindlist', как описано выше. Если 'lapply' действительно перетаскивает вас, вы можете посмотреть на' multicore :: mclapply' – C8H10N4O2

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