r语言 - 对于已经采用'long'格式的数据框,如何在不转置整个数据框的情况下使测量变量成为 ID 变量?



我正在使用以长格式返回必要数据的包(brapi)对数据库进行调用。api将某些ID变量视为测量变量,这是有问题的,因为我的分析脚本需要它们作为ID变量。我不能以这样一种方式修改对数据库的调用,即它会为我做这件事,我不想只使用reshape2::cast,然后融化整个东西,因为有数百个变量会使它变得昂贵。理想情况下,我正在寻找一种使用reshape2plyr等来实现这一点的方法。

使用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数据帧中测量了所有汽车的mpgdisp,并且我们想要除了数据帧中的车型名称之外的其他识别汽车的信息作为其自己的列。为了识别汽车,你有一列汽车名称(我已经调整了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))

只需从起点向数据帧添加新列。

我认为这个解决方案是针对具体情况的,所以我不确定它在您的数据中是否有效,但也许它会有助于思考问题。

最新更新