2016-08-22 2 views
0

Я смотрю, как хранить несколько экземпляров разных типов переменных в R. Я пытался использовать dataframes (и списки), но не могу заставить его делать то, что я хочу. Позвольте мне попытаться показать вам пример, которого я хотел бы достичь.многоуровневый кадр данных

Скажем, я создать тип типа данных (корзины), который содержит номер и строку, например:

iNbLine = 2 
df<-data.frame(Weight=double(iNbLine), Color=character(iNbLine),stringsAsFactors=F) 
row.names(df)<-c("apples","pears") 
df 
     Weight Color 
apples  0  
pears  0  

теперь я могу обновить свою структуру данных, как я хочу. Например:

df$Weight[1]=158 
df$Color[1]="green" 
df 
     Weight Color 
apples 158 green 
pears  0  

То, что я хотел бы сделать, однако есть данные более высокого уровня, чем содержит некоторые из этих корзин с дополнительными данными (здесь цена), поэтому я попытался это:

iNbBasket =5 
df2<-data.frame(Price=double(iNbBasket), Basket=rep(df,iNbBasket)) 

Но это дает мне

Error in data.frame(Price = double(iNbBasket), Basket = rep(df, iNbBasket)) : arguments imply differing number of rows: 5, 2 

То, что я хотел бы быть в состоянии сделать, это получить доступ вес яблок моей 2-ой корзины, например, сохраняя при этом возможность установить цену второй корзины. Надеюсь, это достаточно ясно. На языке C я думаю, что мне удалось определить новый тип данных (корзина) с помощью «struct», который затем я мог бы включить в другой тип данных, но я не могу понять, как это сделать здесь.

Для @joran это попытка показать, что я хотел бы:

     Baskets  
Name Price Names Weight Color 
Basket1 250  apples 158  green 
       pears 32  yellow 
Basket2 120  apples 70  green 
       pears 10  yellow 

Но, будучи в состоянии получить доступ к линии 3, что-то вроде:

myBasket<-myData[2] 
myBasket$Weight[1] 
70 

и сделать:

myBasket$Price = 130 

Обновление 1 Я смотрел через списки, типы переменных S3 и dplyr. Я должен признать, что я не все понял, но пока у меня нет именно того, чего я хочу. Я в настоящее время необходимо сделать следующее

iNbLine = 2 
df<-data.frame(Weight=double(iNbLine), Color=c("green","yellow"),stringsAsFactors=F) 
row.names(df)<-c("apples","pears") 

iNbBasket=3 
dfBaskets<-data.frame(Price=double(iNbBasket)) 
row.names(dfBaskets)=c("Basket1","Basket2","Basket3") 

lBasketsContent<-list() 
for(i in 1:iNbBasket){ 
    lBasketsContent[[i]]=df 
} 

Таким образом, я могу получить доступ цена:

iBasket =2 
dfBaskets$Price[2] = 150 

и любой элемент данной корзины:

lBasketsContent[[2]]$Weight[1] = 300 

, а также самой корзины (I передать его функции в моем реальном случае)

Легко читается, но требуется 2 контейнера.

+0

Как правило, кадр данных может быть представлен как единая прямоугольная сетка элементов данных (т.е. подумайте о таблице). Можете ли вы изменить свой вопрос, чтобы включить то, что должна выглядеть прямоугольная сетка для желаемого результата? – joran

+0

Посмотрите на объекты S3 и S4 или посмотрите на создание многомерной матрицы –

+0

@joran, ОК, тогда кадр данных не то, что я хочу, поскольку мне нужны несколько уровней данных. – Djiggy

ответ

1

Hadley's tidyrpurrr) обеспечивает что-то вроде этого. Взгляните на "tidyr 0.4.0" для демонстрации сложных структур, вложенных в ячейку data.frame.

Их примеры обычно полагаются на наличие соответствующей информации в других ячейках до, заполняющих другие, и даже затем заполняющих их на основе какой-либо формы группировки.Например, с помощью mtcars:

library(dplyr) 
library(tidyr) 
library(purrr) 

mtcars %>% 
    transmute(model = rownames(mtcars), mpg, cyl, disp, gear) %>% 
    group_by(cyl) 
# Source: local data frame [32 x 5] 
# Groups: cyl [3] 
#    model mpg cyl disp gear 
#    <chr> <dbl> <dbl> <dbl> <dbl> 
# 1   Mazda RX4 21.0  6 160.0  4 
# 2  Mazda RX4 Wag 21.0  6 160.0  4 
# 3   Datsun 710 22.8  4 108.0  4 
# 4  Hornet 4 Drive 21.4  6 258.0  3 
# 5 Hornet Sportabout 18.7  8 360.0  3 
# 6   Valiant 18.1  6 225.0  3 
# 7   Duster 360 14.3  8 360.0  3 
# 8   Merc 240D 24.4  4 146.7  4 
# 9   Merc 230 22.8  4 140.8  4 
# 10   Merc 280 19.2  6 167.6  4 
# # ... with 22 more rows 

Если мы называем nest() на группировку, вы можете увидеть, как все уплотняется немного:

quux1 <- mtcars %>% 
    transmute(model = rownames(mtcars), mpg, cyl, disp, gear) %>% 
    group_by(cyl) %>% 
    nest() 
quux1 
# # A tibble: 3 x 2 
#  cyl    data 
# <dbl>   <list> 
# 1  6 <tibble [7 x 4]> 
# 2  4 <tibble [11 x 4]> 
# 3  8 <tibble [14 x 4]> 
quux1$data[[1]] 
# # A tibble: 7 x 4 
#   model mpg disp gear 
#   <chr> <dbl> <dbl> <dbl> 
# 1  Mazda RX4 21.0 160.0  4 
# 2 Mazda RX4 Wag 21.0 160.0  4 
# 3 Hornet 4 Drive 21.4 258.0  3 
# 4  Valiant 18.1 225.0  3 
# 5  Merc 280 19.2 167.6  4 
# 6  Merc 280C 17.8 167.6  4 
# 7 Ferrari Dino 19.7 145.0  5 

Вы можете сделать некоторую обработку этого dplyr -стиль:

quux2 <- mtcars %>% 
    transmute(model = rownames(mtcars), mpg, cyl, disp, gear) %>% 
    group_by(cyl) %>% 
    nest() %>% 
    mutate(mpg2 = purrr::map(data, ~ lm(mpg ~ disp + gear, data = .))) 
quux2 
# # A tibble: 3 x 3 
#  cyl    data  mpg2 
# <dbl>   <list> <list> 
# 1  6 <tibble [7 x 4]> <S3: lm> 
# 2  4 <tibble [11 x 4]> <S3: lm> 
# 3  8 <tibble [14 x 4]> <S3: lm> 

И дело с моделями по отдельности:

summary(quux2$mpg2[[2]]) 
# Call: 
# lm(formula = mpg ~ disp + gear, data = .) 
# Residuals: 
#  Min  1Q Median  3Q  Max 
# -3.2691 -1.7130 0.0708 1.7617 3.4351 
# Coefficients: 
#    Estimate Std. Error t value Pr(>|t|) 
# (Intercept) 30.77234 7.33123 4.197 0.00301 ** 
# disp  -0.13189 0.03094 -4.263 0.00275 ** 
# gear   2.38529 1.54132 1.548 0.16032 
# --- 
# Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 
# Residual standard error: 2.623 on 8 degrees of freedom 
# Multiple R-squared: 0.7294, Adjusted R-squared: 0.6618 
# F-statistic: 10.78 on 2 and 8 DF, p-value: 0.005361 

Более надежное использование этого, конечно, будет иметь дело с программами, но это только начало.

NB: Я не утверждаю, что mpg ~ disp + gear разумная модель :-)

Update 1

Как об этом:

Начать с "по умолчанию" содержимое корзины, гибридный список/data.frame:

df <- list(Price = 0, 
      Contents = data.frame(Names = c("apples", "pears"), 
           Weight = rep(0, 2L), 
           Color = c("green","yellow"), 
           stringsAsFactors = F) 
      ) 

Создать список из трех корзин (три клиента):

nBaskets <- 3L 
# start with 3 empty baskets 
lBaskets <- replicate(nBaskets, df, simplify = FALSE) 
str(lBaskets) 
# List of 3 
# $ :List of 2 
# ..$ Price : num 0 
# ..$ Contents:'data.frame': 2 obs. of 3 variables: 
# .. ..$ Names : chr [1:2] "apples" "pears" 
# .. ..$ Weight: num [1:2] 0 0 
# .. ..$ Color : chr [1:2] "green" "yellow" 
# $ :List of 2 
# ..$ Price : num 0 
# ..$ Contents:'data.frame': 2 obs. of 3 variables: 
# .. ..$ Names : chr [1:2] "apples" "pears" 
# .. ..$ Weight: num [1:2] 0 0 
# .. ..$ Color : chr [1:2] "green" "yellow" 
# $ :List of 2 
# ..$ Price : num 0 
# ..$ Contents:'data.frame': 2 obs. of 3 variables: 
# .. ..$ Names : chr [1:2] "apples" "pears" 
# .. ..$ Weight: num [1:2] 0 0 
# .. ..$ Color : chr [1:2] "green" "yellow" 

Теперь клиент 2 хочет что-то купить:

cust <- 2 
lBaskets[[ cust ]]$Contents$Weight[1] <- 300 
lBaskets[[ cust ]]$Price <- 150 
lBaskets[[ cust ]] 
# $Price 
# [1] 150 
# $Contents 
# Names Weight Color 
# 1 apples 300 green 
# 2 pears  0 yellow 

Не вдаваясь в объекты S4 (возможно, избыточны для того, что вы пытаетесь do), я думаю, что это самый прямой путь. Если вам нужно/нужно быстро обратиться к конкретному клиенту Contents и переназначить его обратно в список, это, безусловно, выполнимо, но не обязательно.

+0

??? неправильный вопрос или ??? – Djiggy

+0

Вы запросили несколько уровней в data.frames. Вот что это может дать вам, хотя и в другой перспективе. Я неправильно понял, когда вы предложили, чтобы целый файл данных был встроен в ячейку другого data.frame? – r2evans

+0

О, я думаю, я вижу, что вам неинтересно в * обработке * вложенных data.frames, просто презентация, в которой переменные группировки слева не повторяются. То есть, вам действительно не нужно, чтобы он был встроен, просто красиво напечатан. Это правильно? – r2evans

0

Мы должны превратить первую data.frame в матрицу и использовать byrow=TRUE

iNbLine = 2 
DF<-data.frame(Weight=double(iNbLine), Color=character(iNbLine),stringsAsFactors=F) 
row.names(DF)<-c("apples","pears") 
DF 

DF$Weight[1]=158 
DF$Color[1]="green" 
DF$Weight[2]=200 
DF$Color[2]="red" 


iNbBasket =5 
DF_MultiLevel<-data.frame(Price=double(iNbBasket), Basket= matrix(rep(DF,iNbBasket),nrow=iNbBasket,byrow=TRUE)) 

#> DF_MultiLevel 
# Price Basket.1 Basket.2 
#1  0 158, 200 green, red 
#2  0 158, 200 green, red 
#3  0 158, 200 green, red 
#4  0 158, 200 green, red 
#5  0 158, 200 green, red 
+0

Не уверен, что это работает, Basket1 содержит все веса и Basker2 содержит все цвета – Djiggy

+0

Это необходимо, потому что @Osssan решил использовать 'array' ('matrix' - это специальный массив). В «массиве» все значения должны иметь один и тот же тип, преобразование с повышением частоты («целое число» <'числовой символ <символ»), если смешанный класс. – r2evans

1

Использование lists. Списки являются общими векторы, способные содержать другие объекты

Использование data.table, например:

> library(data.table) 
> baskets = data.table( 
    'name'=c('basket1','basket2'), 
    'price'=c(250,120), 
    'names'=list(list('apples','pears') , list('apples','pears')), 
    'weight'=list(list(158,32) , list(70,10)), 
    'color'=list(list('green','yellow') , list('green','yellow')) 
) 

> baskets 
     name price names weight color 
1: basket1 250 <list> <list> <list> 
2: basket2 120 <list> <list> <list> 
> 

захватывая первую строку информации

> baskets[1][['price']] 
[1] 250 
> baskets[1][['names']][[1]][[2]] 
[1] "pears" 
> baskets[1][['weight']][[1]][[2]] 
[1] 32 
+0

Спасибо, но в моем случае мне нужно иметь возможность извлекать каждую «корзину» в качестве переменной, которую я могу легко передать другой функции. Мое самое лучшее решение - иметь один фрейм данных, содержащий имена корзин и цену с одной стороны, и список того же размера, что и все мои корзины с другой стороны. Это не приятно, но я работаю, пока не нахожусь лучше. – Djiggy

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