我正在使用以长格式返回必要数据的包(brapi
)对数据库进行调用。api将某些ID变量视为测量变量,这是有问题的,因为我的分析脚本需要它们作为ID变量。我不能以这样一种方式修改对数据库的调用,即它会为我做这件事,我不想只使用reshape2::cast
,然后融化整个东西,因为有数百个变量会使它变得昂贵。理想情况下,我正在寻找一种使用reshape2
、plyr
等来实现这一点的方法。
使用mtcars
内置数据帧可以看出我的问题。假设您从数据库中得到一个长数据帧meltedcars
,其中gear作为ID变量,但您也希望cyl
作为ID变量。我尝试了明显的dcast
命令(如下图所示),但我知道它不起作用,因为函数找不到cyl
作为变量。
meltedcars<-melt(mtcars, id.vars = c("gear"))
head(meltedcars)
gear variable value
1 4 mpg 21.0
2 4 mpg 21.0
3 4 mpg 22.8
4 3 mpg 21.4
5 3 mpg 18.7
6 3 mpg 18.1
c<-dcast(d, gear + cyl ~ variable, value.var= "value")
Error in FUN(X[[i]], ...) : object 'cyl' not found
我已经尝试了上面dcast
函数的多次迭代,但都没有成功。我已经找了很长一段时间类似的问题,但没有找到合适的。我知道我可以用一些环来做这件事,或者重新熔化和铸造,但我想看看是否有更优雅的解决方案。想法?
编辑
我应该更清楚。就本文而言,ID列是长格式的变量,用于识别正在观察的对象,而不是正在测量的对象。假设我们在mtcars
数据帧中测量了所有汽车的mpg
和disp
,并且我们想要除了数据帧中的车型名称之外的其他识别汽车的信息作为其自己的列。为了识别汽车,你有一列汽车名称(我已经调整了mtcars
,使行名称现在是mtcars中名为model
的一列),一列它们是什么gear
,一列表示每辆汽车有多少cyl
。然后我们有一个变量列和值列,其中分别列出了观察的类型和值。当我调用数据库时,我得到的是:
磁头(mtcarsFromDB)
model gear variable value
1 Mazda RX4 4 mpg 21.0
2 Mazda RX4 Wag 4 mpg 21.0
3 Datsun 710 4 mpg 22.8
4 Hornet 4 Drive 3 mpg 21.4
5 Hornet Sportabout 3 mpg 18.7
6 Valiant 3 mpg 18.1
但我想用cyl
重新格式化这个df,它目前是一个变量的值,作为一个像gear
一样的ID列,而不需要铸造和熔化整个内容。它应该是这样的:
model gear cyl variable value
1 Mazda RX4 4 6 mpg 21.0
2 Mazda RX4 Wag 4 6 mpg 21.0
3 Datsun 710 4 4 mpg 22.8
4 Hornet 4 Drive 3 6 mpg 21.4
5 Hornet Sportabout 3 8 mpg 18.7
6 Valiant 3 6 mpg 18.1
我将使用您使用mtcars
:的方法来复制问题
df <- head(mtcars) # get a small chunk to work with
df <- df %>%
mutate(id = paste0("id", row_number())) # create an id variable
# use tidyr::gather() to "melt" the data:
df_long <- df %>%
gather()
此时,df_long
应该是您所指示的"问题"格式。
# Here's the problem area. Focus in on the last '10':
df_long %>% tail(10)
key value
63 carb 1
64 carb 1
65 carb 2
66 carb 1
67 id id1
68 id id2
69 id id3
70 id id4
71 id id5
72 id id6
所以,id
混合在一起。我想这是你的问题吗?以下不是很优雅,但它有效:
# get the id strings, store in `ids`
ids <- df_long %>%
filter(key == "id") %>%
select(value) %>%
.[[1]]
现在,跨行重复id,最后删除上面tail
中的原始id行:
df_long <- df_long %>%
mutate(newid = rep(ids, length(unique(.$key)))) %>%
filter(key != "id") %>%
select(newid, key, value)
head(df_long)
结果:
newid key value
1 id1 mpg 21
2 id2 mpg 21
3 id3 mpg 22.8
4 id4 mpg 21.4
5 id5 mpg 18.7
6 id6 mpg 18.1
我正在创建与您编辑中相同的数据集。
# prepare data
cars <- mtcars
cars$model <- row.names(cars)
row.names(cars) <- seq_along(cars$mpg)
df <- melt(cars, id.vars = c("model", "gear"))
现在,我通过"cyl"观测对df进行子集划分,并将其复制9次,以匹配熔化的数据帧。是什么给了我一个长格式的"cyl"列,它的值重复了9次,与熔化的df的顺序一致。
df1 <- df[df$variable == "cyl", ]
names(df1)[4] <- "cyl"
df1$variable <- NULL
df <- df[df$variable != "cyl", ]
# replicate data frame 9 times
df2 <- do.call("rbind", replicate(9, df1, simplify = FALSE))
只需从起点向数据帧添加新列。
我认为这个解决方案是针对具体情况的,所以我不确定它在您的数据中是否有效,但也许它会有助于思考问题。