3

我一直在寻找有关美国命名趋势的一些数据。我设法获得了 2008 年出生的婴儿的前 1000 个名字。数据格式如下:

 male.name n.male female.name n.female
 Jacob 22272 Emma 18587
 Michael 20298 Isabella 18377
 Ethan 20004 Emily 17217
 Joshua 18924 Madison 16853
 Daniel 18717 Ava 16850
 Alexander 18423 Olivia 16845
 Anthony 18158 Sophia 15887
 William 18149 Abigail 14901
 Christopher 17783 Elizabeth 11815
 Matthew 17337 Chloe 11699

我想得到一个data.frame有 2 个变量的:namegender. 这可以通过循环来完成,但我认为它解决这个问题的效率很低。我认为某些reshape功能将满足我的需求。

让我们假设这个制表符分隔的数据被保存到一个data.frame命名的bnames. 循环可以用函数完成:

 tmp <- character()
  for (i in 1:nrow(bnames)) {
  tmp <- c(tmp, rep(bnames[i,1], bnames[i,2]))
 }

但我想用基于矢量的方法来实现这一点。有什么建议么?

4

4 回答 4

5

因此,一个快速版本是转换 data.frame 并使用该rbind()函数来获得您想要的。

dataNEW <- data.frame(bnames[,1],c("m"), bnames[,c(2,3)], c("f"), bnames[,4])
colnames(dataNEW) <- c("name", "gender", "value", "name", "gender", "value")

这会给你:

          name gender value      name gender value
1        Jacob      m 22272      Emma      f 18587
2      Michael      m 20298  Isabella      f 18377
3        Ethan      m 20004     Emily      f 17217
4       Joshua      m 18924   Madison      f 16853
5       Daniel      m 18717       Ava      f 16850
6    Alexander      m 18423    Olivia      f 16845
7      Anthony      m 18158    Sophia      f 15887
8      William      m 18149   Abigail      f 14901
9  Christopher      m 17783 Elizabeth      f 11815
10     Matthew      m 17337     Chloe      f 11699

现在您可以使用rbind()

dataNGV <- rbind(dataNEW[1:3],dataNEW[4:6])

这导致:

      name gender value
1        Jacob      m 22272
2      Michael      m 20298
3        Ethan      m 20004
4       Joshua      m 18924
5       Daniel      m 18717
6    Alexander      m 18423
7      Anthony      m 18158
8      William      m 18149
9  Christopher      m 17783
10     Matthew      m 17337
11        Emma      f 18587
12    Isabella      f 18377
13       Emily      f 17217
14     Madison      f 16853
15         Ava      f 16850
16      Olivia      f 16845
17      Sophia      f 15887
18     Abigail      f 14901
19   Elizabeth      f 11815
20       Chloe      f 11699
于 2010-02-03T07:10:20.413 回答
3

我认为(如果我理解正确的话)mropa 的解决方案需要多一步才能得到你想要的

library(plyr)
data <- ddply(dataNGV, .(name,gender), 
      function(x) data.frame(name=rep(x[,1],x[,3]),gender=rep(x[,2],x[,3])))
于 2010-02-03T08:19:45.487 回答
3

基于直接向量的解决方案(替换循环)将是

# your data:
bnames <- read.table(textConnection(
"male.name n.male female.name n.female
Jacob 22272 Emma 18587
Michael 20298 Isabella 18377
Ethan 20004 Emily 17217
Joshua 18924 Madison 16853
Daniel 18717 Ava 16850
Alexander 18423 Olivia 16845
Anthony 18158 Sophia 15887
William 18149 Abigail 14901
Christopher 17783 Elizabeth 11815
Matthew 17337 Chloe 11699
"), sep=" ", header=TRUE, stringsAsFactors=FALSE)

# how to avoid loop
bnames$male.name[ rep(1:nrow(bnames), times=bnames$n.male) ]

它基于这样一个事实,即rep可以一次做你在循环中做的事情。

但是对于最终结果,您应该结合 mropa 和 gd047 答案。

或者用我的解决方案:

data_final <- data.frame(
  name = c(
    bnames$male.name[ rep(1:nrow(bnames), times=bnames$n.male) ],
    bnames$female.name[ rep(1:nrow(bnames), times=bnames$n.female) ]
  ),
  gender = rep(
    c("m", "f"),
    times = c(sum(bnames$n.male), sum(bnames$n.female))
  ),
  stringsAsFactors = FALSE
)

[编辑] 简化:

data_final <- data.frame(
  name = rep(
    c(bnames$male.name, bnames$female.name),
    times = c(bnames$n.male, bnames$n.female)
  ),
  gender = rep(
    c("m", "f"),
    times = c(sum(bnames$n.male), sum(bnames$n.female))
  ),
  stringsAsFactors = FALSE
)
于 2010-02-03T10:21:47.540 回答
2

或者,从http://github.com/hadley/data-baby-names下载完整的(清理后的)婴儿姓名数据集。

于 2010-02-03T14:38:54.097 回答