R:将相同的行合并为一个(最好使用 dplyr/tidyr)
R: Combining identical rows into one (preferably using dplyr/tidyr)
我有一个问题我似乎无法弄清楚
我有一个这样的数据框
df <- data.frame(c(rep_len("a",3), "b", "b"), c(rep_len(55, 3), 44, 44),c(rep_len(12, 3), 6, 6), c("na", 2, "na", 3, "na"), c("na", "na", 4, "na", 8), c(5, "na", "na", "na", "na"))
names(df) <- c("street", "latitude", "longitude", "A", "B", "C")
street latitude longitude A B C
a 55 12 na na 5
a 55 12 2 na na
a 55 12 na 4 na
b 44 6 3 na na
b 44 6 na 8 na
我想我正在寻找的是一种折叠 'street'、'latitude'、'longitude' 中具有相同值的行的方法,因此数据框看起来像这样
street latitude longitude A B C
a 55 12 2 4 5
b 44 6 3 8 na
我最好的尝试是:
df %>%
group_by(street) %>%
summarise_each(funs(first))
但不太对。有什么想法吗?
我不明白为什么你有 "na"
个字符串 - R 有一个 NA
代表 characters/factors。无论如何,对于您的示例,也许您正在寻找这个:
library(data.table)
dt = as.data.table(df) # or convert in place using setDT
dt[, lapply(.SD, function(x) x[x != "na"]), by = .(street, latitude, longitude)]
# street latitude longitude A B C
#1: a 55 12 2 4 5
#2: b 44 6 3 8 NA
要扩展@mlt 的评论,您可以使用 tidyr
(reshape2
的后继者)来重塑它。看起来像
df %>%
gather(type, value, -c(street, latitude, longitude)) %>%
na.omit %>%
spread(type, value)
这会将 A/B/C 列展开成行,省略 NA 字段,然后将它们展开。
如@eddi 所述,您需要使用内置 NA
值而不是字符串 "na"。我用了
dfs <- 'street latitude longitude A B C
a 55 12 NA NA 5
a 55 12 2 NA NA
a 55 12 NA 4 NA
b 44 6 3 NA NA
b 44 6 NA 8 NA
'
df <- read.table(text=dfs, header=T)
只要您使用标准 NA
代替 "na"
并在创建 df
:
df %>%
group_by(street, latitude, longitude) %>%
summarise_each(funs(ifelse(sum(is.na(.)==FALSE)==0, NA, .[which(is.na(.)==FALSE)])), matches("[A-Z]{1}"))
# Result
street latitude longitude A B C
1 a 55 12 2 4 5
2 b 44 6 3 8 NA
如果您更愿意坚持使用 "na"
,那么这个可行:
df %>%
group_by(street, latitude, longitude) %>%
summarise_each(funs(ifelse(sum(.!="na")==0, "na", .[which(.!="na")])), matches("[A-Z]{1}"))
我有一个问题我似乎无法弄清楚
我有一个这样的数据框
df <- data.frame(c(rep_len("a",3), "b", "b"), c(rep_len(55, 3), 44, 44),c(rep_len(12, 3), 6, 6), c("na", 2, "na", 3, "na"), c("na", "na", 4, "na", 8), c(5, "na", "na", "na", "na"))
names(df) <- c("street", "latitude", "longitude", "A", "B", "C")
street latitude longitude A B C
a 55 12 na na 5
a 55 12 2 na na
a 55 12 na 4 na
b 44 6 3 na na
b 44 6 na 8 na
我想我正在寻找的是一种折叠 'street'、'latitude'、'longitude' 中具有相同值的行的方法,因此数据框看起来像这样
street latitude longitude A B C
a 55 12 2 4 5
b 44 6 3 8 na
我最好的尝试是:
df %>%
group_by(street) %>%
summarise_each(funs(first))
但不太对。有什么想法吗?
我不明白为什么你有 "na"
个字符串 - R 有一个 NA
代表 characters/factors。无论如何,对于您的示例,也许您正在寻找这个:
library(data.table)
dt = as.data.table(df) # or convert in place using setDT
dt[, lapply(.SD, function(x) x[x != "na"]), by = .(street, latitude, longitude)]
# street latitude longitude A B C
#1: a 55 12 2 4 5
#2: b 44 6 3 8 NA
要扩展@mlt 的评论,您可以使用 tidyr
(reshape2
的后继者)来重塑它。看起来像
df %>%
gather(type, value, -c(street, latitude, longitude)) %>%
na.omit %>%
spread(type, value)
这会将 A/B/C 列展开成行,省略 NA 字段,然后将它们展开。
如@eddi 所述,您需要使用内置 NA
值而不是字符串 "na"。我用了
dfs <- 'street latitude longitude A B C
a 55 12 NA NA 5
a 55 12 2 NA NA
a 55 12 NA 4 NA
b 44 6 3 NA NA
b 44 6 NA 8 NA
'
df <- read.table(text=dfs, header=T)
只要您使用标准 NA
代替 "na"
并在创建 df
:
df %>%
group_by(street, latitude, longitude) %>%
summarise_each(funs(ifelse(sum(is.na(.)==FALSE)==0, NA, .[which(is.na(.)==FALSE)])), matches("[A-Z]{1}"))
# Result
street latitude longitude A B C
1 a 55 12 2 4 5
2 b 44 6 3 8 NA
如果您更愿意坚持使用 "na"
,那么这个可行:
df %>%
group_by(street, latitude, longitude) %>%
summarise_each(funs(ifelse(sum(.!="na")==0, "na", .[which(.!="na")])), matches("[A-Z]{1}"))