(从Stata到R)数据探索和变量创建:count,list,bysort,egen

时间:2014-12-18 21:38:37

标签: r sorting data-mining stata subset

尝试从Stata过渡到R是令人兴奋和具有挑战性的,但我在R中仍在努力的一个领域是数据探索,然后是随后的变量创建。具体来说,如何

  1. 计算变量的值(Stata的 count 命令)

    count if var 2==3
    /* counts the number of observations that have a value of 3 on var2 */
    
  2. 列出满足条件的观察结果(Stata的如果限定符)

    list id if var7 < 8
    /*lists the ID of observations with a value less than 8 on var7 */
    
  3. 按分组变量制表(Stata的 bysort 命令)

    bysort var3: tab1 var2 var9 if var8=2 | var1 !=11
    /* create a two-way frequency table for those observations of var2 and var9 where
       var8 is 2 or var1 isn't 11 */
    
  4. 从另一个创建新变量(Stata的 egen 命令)

    egen var3 = count(var1), by(var2)
    /* creates var3 as the total observations in var1, for each category in var2;
       here var2 is a categorical variable, so, this code seeks to count the frequency
       of var1 (say, 'trades' among NFL teams), counted separately by each category of
       var2 (say, 32 different NFL teams). */
    

1 个答案:

答案 0 :(得分:6)

我最后试着回答你的问题。首先,使用示例数据框:

set.seed(123)
df <- data.frame(id=c(paste0(letters[1:10], 1:10)), matrix(sample(1:20, 500, replace=T), nrow=100,     ncol=5))
colnames(df)[2:6] <- paste0("var", 1:5)

1。计算变量

的值

对于第一个问题,我不确定为什么你不会用table(var2)执行此操作,但如果你愿意,有几种方法可以做到。

count if var2==3       /* counts the number of observations that 
                          have a value of 3 on var2 */

第一个我试图复制Stata在你要求它计算时所做的事情。在这里,我们对var2==3的数据框进行子集化,然后计算行数。

nrow(df[df$var2==3, ])

您可以更直接地执行此操作,方法是使用向量df$var2==3,它是一个长度与TRUE/FALSE相同的逻辑nrow(df)向量,并对值进行求和,这将隐式转换矢量从逻辑到0/1

sum(df$var2==3)

2。列出满足条件的值

第二个问题也基本上归结为子集化,一般来说,我认为在Stata中使用if的内容归结为具有相同逻辑条件的R数据帧的子集化。

list id if var7 < 8    /* lists the ID of observations with a 
                          value less than 8 on var7 */

因此,我们通过将行限制为符合条件var5 < 8的行并选择我们想要的变量id来对数据框进行子集化。

df$id[df$var5 < 8]
# or
df[df$var5 < 8, "id"]
# or
subset(df, var5 < 8, select="id")
# or
with(df, id[var5 < 8])

人们通常don't recommend subset。如果要选择名称包含在另一个对象中的变量,第二种方法很有用,例如:

want <- c("id", "var1")
df[df$var5 < 8, want]

3。按变量列表

最后两个有点棘手。

bysort var3: tab1 var2 var9 if var8=2 | var1 !=11 /* create a series of separate 
                         two-way frequency tables for those observations of var2
                         and var9 where var8 is 2 or var1 isn't 11 */

我们可以首先对我们想要的数据进行子集化,然后使用byvar2var3制成var1表格。

foo <- df[df$var4==20 | df$var5==7, ]
by(foo, foo$var1, function(x) table(x[, c("var2", "var3")]))

我认为function(x)部分称为匿名函数,在您使用byapply等函数时很常见。by的调用将会中断foovar1分成几部分,然后将其作为匿名函数的参数传递,即x。传递的内容是foo的子集,因此是包含原始变量名称的数据框,这就是为什么我们可以像x一样对foo进行分组的原因。

从技术上讲,您也可以将所有三个添加到table调用中,但这对于如此多的变量值不能很好地运行:

table(foo$var2, foo$var3, foo$var1)

4。非遗漏观察(?)

最后一个问题有点奇怪。 var1 var2的计数是否只是var2中值的频率,除非缺少值?我假设当时缺少值。

egen var3 = count(var1), by(var2)  /* creates var3 as the total observations in 
                                      var1, for each category in var2 */

所以我们在这里按dfdf$var2分解为分区,然后应用一个函数来计算var3中的非缺失值。最后一位将其更改为具有var2值和非缺失var3计数的数据帧。

v3obs <- by(df, df$var2, function(x) sum(!is.na(x$var3)))
v3obs[]

v3obs <- data.frame(var2=names(v3obs[]), var6=v3obs[])

我们现在可以将结果合并回我们的数据框,以复制egen所做的事情。

foo <- merge(foo, v3obs, by="var2", type="left")

您也可以使用for循环执行此操作,循环遍历行,子集var3获取var2的值,并填写计数非缺失观察值。这可能更容易阅读,但效率较低。我可能还有更好的方法,我不知道,by对我来说不是那么直观(我也来自Stata背景)所以我一般都试图避免它。