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()работи добре за отделни колони или рамки с данни, e.g. mapply(nrbind, k$location, k$location) но по някакъв начин не се изпълнява, когато се изпълнява цялата data.frame. Дори ако променя имената на редовете с 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

Използването на обикновена рамка от данни би било предпочитаният от мен начин за това.

[РЕДАКТИРАНЕ:] Опция 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. Получавам грешка за неуникално име на ред. Сега всичките ми имена на редове ще бъдат еднакви. Знаете ли някакви директни решения за това? Това се случи и при изчистване на имената на редовете преди изпълнение на кода ( 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
Все още не мога да заобиколя грешката с уникалните имена на редове. Редактирах въпроса си по-горе, за да включа моя код и изхода за грешка. - person uncool; 22.07.2015
comment
Това се случва, защото вашата рамка с данни съдържа множество нива на влагане. Едва сега го забелязах. A добави рекурсивно решение в моя отговор (опция 3). - person SimonG; 22.07.2015