我在R中使用“dplyr”包来汇总和重新组织数据集。数据集由单个记录组成,并且对于每个个体,可能存在唯一或多个遭遇。我想创建一个新列,如果在第一次收集期间收集的数据不完整,则会考虑后续遇到的信息。以下是一些示例数据:
ID<-rep(1:4,2)
Time<-as.character(c("A","A","A","A","B","B","B","B"))
Color<- as.character(c("u","u","red","red","green","u","u","red"))
Data<- data.frame(ID,Time,Color)
Data
对于上面的数据示例,我想为颜色创建一个新列。对于在时间A中遇到的具有“u”颜色(这表示未知)的个人(ID),在随后的时间(时间B)中将颜色更改为所识别的种类。否则,如果在时间A期间有颜色类型,请保持原样。这是我尝试过的:
library(dplyr)
Data2<-mutate(Data, Color.new=if_else(Color=="u" & Time=="A",
Color=="green"|Color=="red" & Time=="B", NA))
Data2
我希望读取:当Color为“u”且Time为“A”时,Color为其各自的值(绿色或红色),当Time为“B”时,否则保持原样。
我的试验不起作用,如果个别1可能已从未知变为绿色,则会产生具有NAs和FALSE的列。
感谢您的帮助或评论。
答案 0 :(得分:1)
你的ifelse语句不起作用的原因是因为它被设计用于向量:一个要比较的事物的向量,以及两个可能的响应向量。所有这些都必须是相同的长度。在你的情况下,这并没有真正发挥作用。我可以通过两种方式看到解决方案:
1)如果每个人最多有一次&#34; B&#34;观察,最简单的解决方案是使用传播并从tidyr
包收集。 (它们具有与reshape
相同的功能,并且还有许多其他功能可以执行相同的操作 - 这只是我喜欢的功能。
result <- Data %>%
spread(Time, Color) %>%
mutate(
A = as.character(A),
B = as.character(B),
Color1 = case_when(
A == 'u' ~ B,
B == 'u' ~ A,
TRUE ~ A
)) %>% # only run this if you want to go back to the long format
gather(Time, Color, A:B)
# ID Color1 Time Color
# 1 1 green A u
# 2 2 u A u
# 3 3 red A red
# 4 4 red A red
# 5 1 green B green
# 6 2 u B u
# 7 3 red B u
# 8 4 red B red
如果您可以有多个B
,那么使用摘要的方法可能会更好:
Data %>%
group_by(ID) %>%
summarize(
Color1 = if(sum(Color != "u") > 0) paste(unique(Color[Color != "u"]), collapse = "_") else "u"
) %>%
left_join(Data, .)
# ID Time Color Color1
# 1 1 A u green
# 2 2 A u u
# 3 3 A red red
# 4 4 A red red
# 5 1 B green green
# 6 2 B u u
# 7 3 B u red
# 8 4 B red red
答案 1 :(得分:0)
您可以使用tidyr::fill
library(tidyverse)
Data[Data =="u"] <- NA
Data %>% group_by(ID) %>% fill(Color,.direction = "up") %>% ungroup
# # A tibble: 8 x 3
# ID Time Color
# <int> <fctr> <fctr>
# 1 1 A green
# 2 1 B green
# 3 2 A <NA>
# 4 2 B <NA>
# 5 3 A red
# 6 3 B <NA>
# 7 4 A red
# 8 4 B red
此处我们没有针对少数情况的后续信息,因此仍有一些NAs
。