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

coi*_*oip 0 sorting r subset data-mining stata

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

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

    count if var 2==3
    /* counts the number of observations that have a value of 3 on var2 */
    
    Run Code Online (Sandbox Code Playgroud)
  2. 列出符合条件的观察结果(Stata's if qualifier)

    list id if var7 < 8
    /*lists the ID of observations with a value less than 8 on var7 */
    
    Run Code Online (Sandbox Code Playgroud)
  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 */
    
    Run Code Online (Sandbox Code Playgroud)
  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). */
    
    Run Code Online (Sandbox Code Playgroud)

and*_*ega 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)
Run Code Online (Sandbox Code Playgroud)

1.计算变量的值

对于第一个问题,我不确定为什么你不会这样做table(var2),但如果你想,有几种方法可以做到这一点.

count if var2==3       /* counts the number of observations that 
                          have a value of 3 on var2 */
Run Code Online (Sandbox Code Playgroud)

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

nrow(df[df$var2==3, ])
Run Code Online (Sandbox Code Playgroud)

您可以通过获取向量来更直接地执行此操作,向量df$var2==3TRUE/FALSE具有相同长度的逻辑向量nrow(df),并对值进行求和,这将隐式地将向量从逻辑转换为0/1

sum(df$var2==3)
Run Code Online (Sandbox Code Playgroud)

2.列出符合条件的值

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

list id if var7 < 8    /* lists the ID of observations with a 
                          value less than 8 on var7 */
Run Code Online (Sandbox Code Playgroud)

因此,我们通过将行限制为满足条件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])
Run Code Online (Sandbox Code Playgroud)

人们通常不建议 subset.如果要选择名称包含在另一个对象中的变量,第二种方法很有用,例如

want <- c("id", "var1")
df[df$var5 < 8, want]
Run Code Online (Sandbox Code Playgroud)

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 */
Run Code Online (Sandbox Code Playgroud)

我们可以通过首先对我们想要的数据进行子集化,然后使用by制表var2var3by来实现var1.

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

function(x)部分被称为匿名函数,我认为,当你使用像功能是常见的by,apply等呼吁by将打破foo由成片var1,然后把它传递为我们的匿名功能,即论证x.传递的是一个子集foo,因此是一个包含原始变量名称的数据框,这就是我们可以x按照相同的方式进行子集化的原因foo.

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

table(foo$var2, foo$var3, foo$var1)
Run Code Online (Sandbox Code Playgroud)

4.非遗漏观察(?)

最后一个问题有点奇怪.不会的计数var1var2只是值的频率var2,除非有遗漏值?我假设那时缺少值.

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

所以这里我们分解df为分区df$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[])
Run Code Online (Sandbox Code Playgroud)

我们现在可以将结果合并回我们的数据框以复制内容egen.

foo <- merge(foo, v3obs, by="var2", type="left")
Run Code Online (Sandbox Code Playgroud)

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