将复数宽数据转换为R中的long

时间:2014-04-04 07:03:54

标签: r reshape performance

我认为我确实将广泛的数据转换为了很长时间,而且我已经使用了一段时间,但我最近发现出了问题。显然,代码是错误的,我似乎无法解决它。

广泛的数据很复杂,因为它包含有关何时开始他/她的第一份工作,第二份工作等的信息。我想把它变成面板数据。

因此原始数据df如下所示:

id name gender job1 sjob1 ejob1 job2 sjob2 ejob2 job3 sjob3 ejob3
1  Jane F      100  1990  1992  103  1993  1995  104  1994  1997
2  Tom  M      200  1978  1980  400  1981  1985  NA   NA    NA

工作号码是工作代码,表示某些工作,如管理,销售等。

以上是我所拥有的完整数据的非常简短的版本。想要的输出是:

id name gender year job
1  Jane F      1990 100
1  Jane F      1991 100
1  Jane F      1992 100
1  Jane F      1993 103
1  Jane F      1994 104
1  Jane F      1995 104
1  Jane F      1996 104
1  Jane F      1997 104
2  Tom  M      1978 200
2  Tom  M      1979 200
2  Tom  M      1980 200
2  Tom  M      1981 400
2  Tom  M      1982 400
2  Tom  M      1983 400
2  Tom  M      1984 400
2  Tom  M      1985 400

对于宽版本,我总共有大约1600个观测值。 (1600人)。我尝试了以下但没有工作:

df_long <-reshape(df,
          varying=c("job1", "job2", "job3"),
          v.names="job",
          timevar="year",
          times=c("sjob1", "sjob2", "sjob3"),
          direction = "long")

这实际上成功地按照sjob1,sjob2,sjob3(每个作业的开始年份)的顺序保存了作业代码但是没有在sjob1下保存年份而是仅记录了sjob1:

 id name gender year job
1  Jane F      sjob1 100
1  Jane F      sjob2 103
1  Jane F      sjob3 104
2  Tom  M      sjob1 200
2  Tom  M      sjob2 400
2  Tom  M      sjob3 NA

以上是我原始数据的示例,因此我也想发布原始数据:https://www.dropbox.com/s/ygbkd91ataqkwz5/origin_wide.RData

3 个答案:

答案 0 :(得分:0)

这是使用reshape2plyr的草图:

第1步:重塑一个&#34; long&#34;格式与您正在寻找的格式有些不同:

library(reshape2)
df.m <- melt(df, id.vars=c("id", "name", "gender"))

这将为您提供作业的开始和结束时间以及分类。

第2步:隔离作业ID:

df.m$job.id <- as.integer(gsub("^(.*job)([0-9]+)$", "\\2", df.m$variable))
df.m$variable <- gsub("^(.*)([0-9]+)$", "\\1", df.m$variable)

步骤3:您可以为每个人ID和工作ID计算工作分类表(以及姓名和性别):

library(plyr)
df.jc <- rename(subset(df.m, variable=="job", select=c("id", "name", "gender", "value")), variable=job)

第4步:要获得完整的结果,您需要dcast数据才能获得更广泛的结果&#34;具有两列sjobejob的格式以及每个作业ID的每人ID一次观察。然后,您可以adply生成一系列年份,然后将其合并回df.jc

我还没有对代码进行测试,也无法为最后一步提供一些东西,因为我无法轻松读取您的示例数据。如果您拥有dput数据,那将会有很大帮助。有关更多问题,请另外提出一个更详细的问题,并提供一些代码和数据。

答案 1 :(得分:0)

您可以使用plyr包执行此操作:

# reading the data
df <- read.table(text = "id name gender job1 sjob1 ejob1 job2 sjob2 ejob2 job3 sjob3 ejob3
1  Jane F      100  1990  1992  103  1993  1995  104  1994  1997
2  Tom  M      200  1978  1980  400  1981  1985  NA   NA    NA", header = TRUE, strip.white = TRUE)

# needed package
require(plyr)

# transforming the data
df2 <- rbind(
  ddply(df, .(id, name, gender), mutate, year = sjob1, job = job1),
  ddply(df, .(id, name, gender), mutate, year = ejob1, job = job1),
  ddply(df, .(id, name, gender), mutate, year = sjob2, job = job2),
  ddply(df, .(id, name, gender), mutate, year = ejob2, job = job2),
  ddply(df, .(id, name, gender), mutate, year = sjob3, job = job3),
  ddply(df, .(id, name, gender), mutate, year = ejob3, job = job3)
)

# getting rid off NA's & ordering the dataframe by id
df2 <- na.omit(df2[order(df2$id),c(1:3,13,14)])

答案 2 :(得分:0)

  1. 首先,我们将数据从宽到长重塑

我们在onetree包中使用reshape_toLong命令将数据从宽到长整形。

devtools::install_github("yikeshu0611/onetree") #install yikeshu0611
library(onetree)
df.long = reshape_toLong(data=df,
                        id="id",
                        j="new",
                        value.var.prefix = c("job","sjob","ejob"))
df. long
   id name gender new job sjob ejob
1  1 Jane      F   1 100 1990 1992
2  1 Jane      F   2 103 1993 1995
3  1 Jane      F   3 104 1994 1997
4  2  Tom      M   1 200 1978 1980
5  2  Tom      M   2 400 1981 1985
6  2  Tom      M   3  NA   NA   NA
  1. 获取sjob和ejob的两个数据。

我们可以在数据df.long中看到,年份变量sjob和ejob是分开的,例如,我们仅获得两个数据框,并且行将它们绑定。

df.sjob=df.long[,-7] #data with sjob
colnames(df.sjob)[6]="year" #change sjob to year

df.sjob
  id name gender new job year
1  1 Jane      F   1 100 1990
2  1 Jane      F   2 103 1993
3  1 Jane      F   3 104 1994
4  2  Tom      M   1 200 1978
5  2  Tom      M   2 400 1981
6  2  Tom      M   3  NA   NA

df.ejob=df.long[,-6] #data with sjob
colnames(df.ejob)[6]="year" #change sjob to year
  id name gender new job year
1  1 Jane      F   1 100 1992
2  1 Jane      F   2 103 1995
3  1 Jane      F   3 104 1997
4  2  Tom      M   1 200 1980
5  2  Tom      M   2 400 1985
6  2  Tom      M   3  NA   NA
  1. 最后一步:rbind

rbind df.sjob和df.ejob

rbind(df.sjob,df.ejob)

   id name gender new job year
1   1 Jane      F   1 100 1990
2   1 Jane      F   2 103 1993
3   1 Jane      F   3 104 1994
4   2  Tom      M   1 200 1978
5   2  Tom      M   2 400 1981
6   2  Tom      M   3  NA   NA
7   1 Jane      F   1 100 1992
8   1 Jane      F   2 103 1995
9   1 Jane      F   3 104 1997
10  2  Tom      M   1 200 1980
11  2  Tom      M   2 400 1985
12  2  Tom      M   3  NA   NA