使用 dplyr 使数据帧看起来像 ftable 的输出——使用 group_by 为某些元素赋值

Using dplyr to make a dataframe look like output from ftable -- assigning a value to certain elements using group_by

例如我有以下高数据帧df:

state <- state.abb[1:10]
county <- letters[1:10]
zipcode <- sample(1000:9999, 5)

library(data.table)
df <- data.frame(CJ(state, county, zipcode))
colnames(df) <- c("state", "county", "zip")
df[1:15,]

   state county  zip
1     AK      a 2847
2     AK      a 2913
3     AK      a 3886
4     AK      a 6551
5     AK      a 8447
6     AK      b 2847
7     AK      b 2913
8     AK      b 3886
9     AK      b 6551
10    AK      b 8447
11    AK      c 2847
12    AK      c 2913
13    AK      c 3886
14    AK      c 6551
15    AK      c 8447

出于演示目的,它可能看起来更好:

   state county  zip
1     AK      a 2847
2               2913
3               3886
4               6551
5               8447
6             b 2847
7               2913
8               3886
9               6551
10              8447
11            c 2847
12              2913
13              3886
14              6551
15              8447

我经常使用 dplyr 来创建交叉表,而不是使用基础 R 的 tableftable 函数,这样我就可以将输出通过管道传输到 xtable HTML 介绍。

为了使它看起来像 ftable 的输出,我想将所有元素设置为 "",但我分组的每一列中的第一个唯一元素除外。我知道我可以使用 group_by 来执行与使用 dplyr 类似的操作,但它似乎不能很好地处理索引,这是我设想完成此任务的唯一方法:

library(dplyr)
df <- group_by(df, state, county)
df[-1,] <- ""

我应该换个方式考虑这个问题,还是有一些方便的 dplyr 语法可以做到这一点?谢谢。

这是一种方法。首先,按 state 对数据进行分组。任何重复的县都将是第一个 mutate() 中的 ""。然后,取消分组数据。给定县,a 出现在每个州的开头,带有 a 的行是您要保留州名的行。否则,你想要 ""。这是在第二个 mutate().

中完成的
group_by(df, state) %>%
mutate(county = order_by(county, ifelse(!duplicated(county), county, ""))) %>%
ungroup() %>%
mutate(state = ifelse(county == "a", state, ""))

#   state county  zip
#1     AK      a 2429
#2               3755
#3               6108
#4               8364
#5               9577
#6             b 2429
#7               3755
#8               6108
#9               8364
#10              9577

在data.table中,上面的代码可能是这样的。

setDT(df)[, county := ifelse(!duplicated(county), county, ""), by = state][,
            state := ifelse(county == "a", state, "")]

setDT(df)[, county := ifelse(!duplicated(county), county, ""), by = state][
            county != "a", state := ""]