使用 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 的 table
或 ftable
函数,这样我就可以将输出通过管道传输到 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 := ""]
例如我有以下高数据帧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 的 table
或 ftable
函数,这样我就可以将输出通过管道传输到 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 := ""]