我正在研究如何在R中存储不同变量类型的多个实例。我试图使用数据帧(和列表),但无法让它做我想要的。让我试着向你展示一下我想要实现的目标。
假设我创建了一种包含数字和字符串的数据类型(一个篮子),如:
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
我希望能够做的是获取我的第二个篮子的苹果的重量;同时保留设定第二篮子价格的可能性。我希望这很清楚。在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
以及篮子本身(我将它传递给我的实际情况中的函数)
dfBasket<-lBasketsContent[[2]]
易于阅读,但需要2个容器。
答案 0 :(得分:1)
哈德利的tidyr
(purrr
)提供了类似的东西。请查看"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
当然,更加强大的使用会以编程方式处理模型,但这只是一个开始。
注意:我并不是说mpg ~ disp + gear
是合理的模式: - )
更新1
这个怎么样:
以&#34开头;默认&#34;篮子内容,混合列表/ 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对象(可能是为了你想做的事情而过度设计),我认为这是最直接的方式。如果您希望/需要快速参考特定客户Contents
并将其重新分配回列表,那肯定是可行但不是必需的。
答案 1 :(得分: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
答案 2 :(得分: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