Rbind, наличие фреймов данных внутри фреймов данных вызывает ошибки?

У меня есть data.frame, который, в свою очередь, содержит data.frames, теперь использование rbind для двух идентичных наборов (например, rbind(k,k)) этих данных вызывает ошибку:

Ошибка в xpdrows.data.frame (x, rows, new.rows): количество заменяемых элементов не кратно длине замены

Ниже представлена ​​структура объекта с данными.

> str(k)
'data.frame':   25 obs. of  18 variables:
 $ location         :'data.frame':  25 obs. of  5 variables:
  ..$ address   :'data.frame':  25 obs. of  1 variable:
  .. ..$ streetAddress: chr  "Astrakangatan 110A" "Västmannagatan 85C" "Doktor Abelins gata 6" "Standarvägen 1" ...
  ..$ position  :'data.frame':  25 obs. of  2 variables:
  .. ..$ latitude : num  59.4 59.3 59.3 59.3 59.3 ...
  .. ..$ longitude: num  17.8 18 18.1 18 18 ...
  ..$ namedAreas:List of 25
  .. ..$ : chr "Hässelby"
  .. ..$ : chr "Vasastan"
  .. ..$ : chr "Södermalm"
  .. ..$ : chr "Gamla Älvsjö"
  .. ..$ : chr "Fruängen-Hägersten"
  .. ..$ : chr "Södermalm"
  .. ..$ : chr "Kungsholmen"
  .. ..$ : chr "Fruängen"
  .. ..$ : chr "Årsta"
  .. ..$ : chr "Telefonplan"
  .. ..$ : chr "Kista"
  .. ..$ : chr "Östberga"
  .. ..$ : chr "Hägerstensåsen"
  .. ..$ : chr "Östermalm"
  .. ..$ : chr "Årsta"
  .. ..$ : chr "Bromma Blackeberg"
  .. ..$ : chr "Similar Listings Overwritten Here"
  .. ..$ : chr "Traneberg"
  .. ..$ : chr "Kungsholmen"
  .. ..$ : chr "Skärholmen"
  .. ..$ : chr "Katarina"
  .. ..$ : chr "Farsta stadsdelsområde"
  .. ..$ : chr "Kista"
  .. ..$ : chr "Bromma"
  .. ..$ : chr "Akalla"
  ..$ region    :'data.frame':  25 obs. of  2 variables:
  .. ..$ municipalityName: chr  "Stockholm" "Stockholm" "Stockholm" "Stockholm" ...
  .. ..$ countyName      : chr  "Stockholms län" "Stockholms län" "Stockholms län" "Stockholms län" ...
  ..$ distance  :'data.frame':  25 obs. of  1 variable:
  .. ..$ ocean: int  NA 2325 1223 6360 NA 329 2630 NA 2837 5537 ...
 $ listPrice        : int  1900000 4100000 4875000 2950000 1995000 1395000 2450000 2250000 2550000 1995000 ...
 $ rent             : int  4678 1586 3092 3983 2587 520 1437 3644 2936 2707 ...
 $ floor            : num  1 1 NA 1 3 0.5 1 6 3 NA ...
 $ livingArea       : num  60 40 70 91 37 11 28 59 54 42 ...
 $ source           :'data.frame':  25 obs. of  4 variables:
  ..$ name: chr  "HusmanHagberg" "BOSTHLM" "Gripsholms Fastighetsförmedling" "Fastighetsbyrån" ...
  ..$ id  : int  1610 1499 9895524 1573 58 713 2091 1566 1566 1566 ...
  ..$ type: chr  "Broker" "Broker" "Broker" "Broker" ...
  ..$ url : chr  "http://www.husmanhagberg.se/" "http://www.bosthlm.se/" "http://gripsholms.se/" "http://www.fastighetsbyran.se/" ...
 $ rooms            : num  2 2 2.5 3.5 2 1 1 2 2 2 ...
 $ published        : Date, format: "2015-07-17" "2015-07-16" "2015-07-15" "2015-07-10" ...
 $ constructionYear : int  2006 NA 1929 1937 NA 1929 1930 2014 1949 1944 ...
 $ objectType       : chr  "Lägenhet" "Lägenhet" "Lägenhet" "Lägenhet" ...
 $ booliId          : int  1920703 1919949 1896584 1917520 1918145 1918049 1917638 1849399 1916805 1826479 ...
 $ soldDate         : Date, format: "2015-07-21" "2015-07-19" "2015-07-20" "2015-07-20" ...
 $ soldPrice        : int  2000000 4100000 5175000 4200000 2500000 1850000 2820000 2600000 2900000 2230000 ...
 $ url              : chr  "https://www.booli.se/bostad/lagenhet/hasselby/astrakangatan+110a/1920703" "https://www.booli.se/bostad/lagenhet/vasastan/vastmannagatan+85c/1919949" "https://www.booli.se/bostad/lagenhet/sodermalm/doktor+abelins+gata+6/1896584" "https://www.booli.se/bostad/lagenhet/gamla+alvsjo/standarvagen+1/1917520" ...
 $ isNewConstruction: int  NA NA NA NA NA NA NA NA NA NA ...
 $ plotArea         : int  NA NA NA NA 0 NA NA NA NA NA ...
 $ AreaSize         : Factor w/ 10 levels "10","20","30",..: 6 4 7 9 3 1 2 5 5 4 ...
 $ PriceDiff        : int  100000 0 300000 1250000 505000 455000 370000 350000 350000 235000 ...

Не рекомендуется ли использовать фреймы данных внутри фреймов данных? Или я ошибся?

@SimonG, ответ отличный. Но я натыкаюсь на ошибку неуникальных имен строк. Теперь, когда nrbind()works отлично работает для отдельных столбцов или фреймов данных, e.g. mapply(nrbind, k$location, k$location) но почему-то не работает при запуске всего data.frame. Даже если я поменяю rownames на row.names, это все равно выдает ошибку.

> nrbind <- function(x,y) if(is.data.frame(x)) rbind(x,y) else c(x,y)
> as.data.frame( mapply(nrbind, k, k) )
 Show Traceback

 Rerun with Debug
 Error in `row.names<-.data.frame`(`*tmp*`, value = value) : 
  duplicate 'row.names' are not allowed In addition: Warning message:
non-unique values when setting 'row.names': ‘1’, ‘10’, ‘11’, ‘12’, ‘13’, ‘14’, ‘15’, ‘16’, ‘17’, ‘18’, ‘19’, ‘2’, ‘20’, ‘21’, ‘22’, ‘23’, ‘24’, ‘25’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’ 

person uncool    schedule 21.07.2015    source источник
comment
Я только что увидел, что ваш фрейм данных содержит несколько уровней вложенности. Я обновил свой ответ ниже.   -  person SimonG    schedule 22.07.2015


Ответы (1)


Мне потребовалось время, чтобы создать «вложенный» фрейм данных, подобный вашему. Лично я бы избегал такой вложенности фреймов данных. Это будет лишь незначительная корректировка вашего кода и позволит вам использовать стандартные функции в R (см. Вариант 2 ниже).

Однако, если вы настаиваете на наличии вложенных фреймов данных, вы можете «имитировать» функциональность rbind, используя mapply, где применяется сочетание rbind и c в зависимости от того, являются ли элементы фрейма данных самими фреймами данных. Я написал небольшой пример для двух фреймов данных (см. Вариант 1 ниже).

Вариант 1. Одноуровневое размещение

a <- letters[1:5]
xy <- data.frame(x=1:5, y=5:1)

k <- data.frame(a)
k[["xy"]] <- xy

# 'data.frame':   5 obs. of  2 variables:
#  $ a : Factor w/ 5 levels "a","b","c","d",..: 1 2 3 4 5
#  $ xy:'data.frame':     5 obs. of  2 variables:
#   ..$ x: int  1 2 3 4 5
#   ..$ y: int  5 4 3 2 1

nrbind <- function(x,y) if(is.data.frame(x)) rbind(x,y) else c(x,y)
as.data.frame( mapply(nrbind, k, k) )

#    a xy.x xy.y
# 1  1    1    5
# 2  2    2    4
# 3  3    3    3
# 4  4    4    2
# 5  5    5    1
# 6  1    1    5
# 7  2    2    4
# 8  3    3    3
# 9  4    4    2
# 10 5    5    1

Обратите внимание, что приведенная выше функция nrbind действительно «быстрая и грязная». Однако настроить его в соответствии с вашими потребностями не составит труда.

Также обратите внимание, что результат mapply больше не будет вложенным фреймом данных. Следовательно, чтобы повторно использовать вариант 1, вы должны расширить функцию nrbind вместо повторного запуска mapply.

Вариант 2: переопределить как обычный data.frame

k <- data.frame(a=a, xy=xy)

# 'data.frame':   5 obs. of  3 variables:
#  $ a   : Factor w/ 5 levels "a","b","c","d",..: 1 2 3 4 5
#  $ xy.x: int  1 2 3 4 5
#  $ xy.y: int  5 4 3 2 1

rbind(k, k) # result as above

Я предпочитаю использовать обычный фрейм данных.

[EDIT:] Вариант 3: более высокие уровни вложенности

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

Можно решить несколько уровней вложенности, сделав все это рекурсивным.

b <- data.frame(a)
b[["z"]] <- data.frame(z1=1:5, z2=5:1)
k <- data.frame(a)
k[["b"]] <- b; k[["xy"]] <- xy

# 'data.frame':   5 obs. of  3 variables:
#  $ a : Factor w/ 5 levels "a","b","c","d",..: 1 2 3 4 5
#  $ b :'data.frame':     5 obs. of  2 variables:
#   ..$ a: Factor w/ 5 levels "a","b","c","d",..: 1 2 3 4 5
#   ..$ z:'data.frame':   5 obs. of  2 variables:
#   .. ..$ z1: int  1 2 3 4 5
#   .. ..$ z2: int  5 4 3 2 1
#  $ xy:'data.frame':     5 obs. of  2 variables:
#   ..$ x: int  1 2 3 4 5
#   ..$ y: int  5 4 3 2 1

recursive.rbind <- function(x,y){
  ll <- lapply(seq_along(x), function(i){ 
    if(is.data.frame(x[[i]])) nrbind(x[[i]],y[[i]]) else rbind(x[i],y[i])
  })
  names(ll) <- names(x)
  as.data.frame(ll)
}

recursive.rbind(k,k)

#    a b.a b.z.z1 b.z.z2 xy.x xy.y
# 1  a   a      1      5    1    5
# 2  b   b      2      4    2    4
# 3  c   c      3      3    3    3
# 4  d   d      4      2    4    2
# 5  e   e      5      1    5    1
# 6  a   a      1      5    1    5
# 7  b   b      2      4    2    4
# 8  c   c      3      3    3    3
# 9  d   d      4      2    4    2
# 10 e   e      5      1    5    1
person SimonG    schedule 21.07.2015
comment
Пожалуйста. Не забудьте принять ответ, если он решил вашу проблему (если, конечно, кто-то не даст ответ получше!) :) - person SimonG; 22.07.2015
comment
Одна небольшая проблема, которая возникла;) При использовании вашего второго варианта с mapply. Я получаю сообщение об ошибке неуникального имени строки. Теперь все мои rownames будут такими же. Вы знаете какие-либо прямые решения этой проблемы? Это произошло также при очистке имен строк перед запуском кода (row.names (k) ‹- NULL) - person uncool; 22.07.2015
comment
Вы уверены? В приведенном выше примере вариант 1 работает с mapply, а вариант 2 работает как с mapply, так и с rbind. Я получаю сообщение об ошибке только при использовании варианта 1 с rbind (с сообщением об ошибке, которое вы описываете). Вы уверены, что у вас правильный k? - person SimonG; 22.07.2015
comment
Да, я использую правильный k. Я здесь немного запутался. В варианте 2, что будет эквивалентом использования реального k для раздела k ‹- data.frame (a = a, xy = xy)? Должен ли я заменить a и xy фреймами данных и другими векторами в реальном k? - person uncool; 22.07.2015
comment
Если вы начинаете с вложенного фрейма данных k, вы можете преобразовать его в обычный фрейм данных с помощью as.data.frame(as.list(k)). - person SimonG; 22.07.2015
comment
Я все еще не могу обойти уникальную ошибку rownames. Я отредактировал свой вопрос выше, чтобы включить свой код и сообщение об ошибке. - person uncool; 22.07.2015
comment
Это происходит потому, что ваш фрейм данных содержит несколько уровней вложенности. Я заметил это только сейчас. В мой ответ добавлено рекурсивное решение (вариант 3). - person SimonG; 22.07.2015