R:更改主题中的重复值
R: Changing Duplicate Values Within Subjects
Subj Trial Time
1 A 1 250
2 A 2 250
3 A 3 280
4 B 1 250
5 B 2 270
6 B 3 290
以上是我正在处理的数据示例。我有不同的受试者 (Subj) 执行同一组试验 (Trial)。不幸的是,当试验事件快速连续发生时,我的设备将打印相同的时间值(请参阅第 1 行和第 2 行的时间列)。
我不能让同一个主题有重复的时间值,但是,不同的主题可以有相同的时间值。因此,我需要一种有条件地更改重复项的方法,以便仅更改特定主题中的时间重复项。
理想情况下,我想将上面的示例更改为如下所示:
Subj Trial Time
1 A 1 250
2 A 2 250.5
3 A 3 280
4 B 1 250
5 B 2 270
6 B 3 290
关于我如何能够完成此任务的任何建议?
谢谢!
使用 dplyr
的解决方案。我们可以按 Subj
和 Time
对数据进行分组,统计出现的次数,然后如果出现的次数超过 1,则通过添加 0.5
来更改 Time
。
library(dplyr)
dt2 <- dt %>%
group_by(Subj, Time) %>%
mutate(Count = row_number()) %>%
ungroup() %>%
mutate(Time = ifelse(Count > 1, Time + 0.5, Time)) %>%
select(-Count)
dt2
# # A tibble: 6 x 3
# Subj Trial Time
# <chr> <int> <dbl>
# 1 A 1 250.0
# 2 A 2 250.5
# 3 A 3 280.0
# 4 B 1 250.0
# 5 B 2 270.0
# 6 B 3 290.0
数据
dt <- read.table(text = " Subj Trial Time
1 A 1 250
2 A 2 250
3 A 3 280
4 B 1 250
5 B 2 270
6 B 3 290",
header = TRUE, stringsAsFactors = FALSE)
有点类似于已经提供的解决方案,但不算。这由两个解决方案组成:
base R
:
do.call(rbind, lapply(split(df, list(df$Subj, df$Time)), function(x) {
x$Time <- x$Time + seq(0, by=0.5, length.out=nrow(x))
x
}))
tidyverse
library(dplyr)
df %>%
group_by(Subj, Time) %>%
mutate(Time2 = Time + seq(0, by=0.5, length.out=n()))
它们都应该产生类似于以下内容的结果:
# Subj Trial Time
# A 1 250.0
# A 2 250.5
# B 1 250.0
# B 2 270.0
# A 3 280.0
# B 3 290.0
关键是将数据帧拆分为由 Subj
和 Time
的列组合定义的块。从这里开始,剩下的就很简单了:从 0
开始,将 Time
列中的值增加 0.5
,这样的序列的长度与块的长度相同。
希望这有用。
这里有一个 base R
选项和 duplicated
。我们根据 'Subj'、'Time' 列创建重复元素的逻辑索引,然后通过向这些元素添加 0.5 来为其分配 'Time' 值。
i1 <- duplicated(df1[c('Subj', 'Time')])
df1$Time[i1] <- df1$Time[i1] + 0.5
df1
# Subj Trial Time
#1 A 1 250.0
#2 A 2 250.5
#3 A 3 280.0
#4 B 1 250.0
#5 B 2 270.0
#6 B 3 290.0
Subj Trial Time
1 A 1 250
2 A 2 250
3 A 3 280
4 B 1 250
5 B 2 270
6 B 3 290
以上是我正在处理的数据示例。我有不同的受试者 (Subj) 执行同一组试验 (Trial)。不幸的是,当试验事件快速连续发生时,我的设备将打印相同的时间值(请参阅第 1 行和第 2 行的时间列)。
我不能让同一个主题有重复的时间值,但是,不同的主题可以有相同的时间值。因此,我需要一种有条件地更改重复项的方法,以便仅更改特定主题中的时间重复项。
理想情况下,我想将上面的示例更改为如下所示:
Subj Trial Time
1 A 1 250
2 A 2 250.5
3 A 3 280
4 B 1 250
5 B 2 270
6 B 3 290
关于我如何能够完成此任务的任何建议?
谢谢!
使用 dplyr
的解决方案。我们可以按 Subj
和 Time
对数据进行分组,统计出现的次数,然后如果出现的次数超过 1,则通过添加 0.5
来更改 Time
。
library(dplyr)
dt2 <- dt %>%
group_by(Subj, Time) %>%
mutate(Count = row_number()) %>%
ungroup() %>%
mutate(Time = ifelse(Count > 1, Time + 0.5, Time)) %>%
select(-Count)
dt2
# # A tibble: 6 x 3
# Subj Trial Time
# <chr> <int> <dbl>
# 1 A 1 250.0
# 2 A 2 250.5
# 3 A 3 280.0
# 4 B 1 250.0
# 5 B 2 270.0
# 6 B 3 290.0
数据
dt <- read.table(text = " Subj Trial Time
1 A 1 250
2 A 2 250
3 A 3 280
4 B 1 250
5 B 2 270
6 B 3 290",
header = TRUE, stringsAsFactors = FALSE)
有点类似于已经提供的解决方案,但不算。这由两个解决方案组成:
base R
:
do.call(rbind, lapply(split(df, list(df$Subj, df$Time)), function(x) {
x$Time <- x$Time + seq(0, by=0.5, length.out=nrow(x))
x
}))
tidyverse
library(dplyr)
df %>%
group_by(Subj, Time) %>%
mutate(Time2 = Time + seq(0, by=0.5, length.out=n()))
它们都应该产生类似于以下内容的结果:
# Subj Trial Time
# A 1 250.0
# A 2 250.5
# B 1 250.0
# B 2 270.0
# A 3 280.0
# B 3 290.0
关键是将数据帧拆分为由 Subj
和 Time
的列组合定义的块。从这里开始,剩下的就很简单了:从 0
开始,将 Time
列中的值增加 0.5
,这样的序列的长度与块的长度相同。
希望这有用。
这里有一个 base R
选项和 duplicated
。我们根据 'Subj'、'Time' 列创建重复元素的逻辑索引,然后通过向这些元素添加 0.5 来为其分配 'Time' 值。
i1 <- duplicated(df1[c('Subj', 'Time')])
df1$Time[i1] <- df1$Time[i1] + 0.5
df1
# Subj Trial Time
#1 A 1 250.0
#2 A 2 250.5
#3 A 3 280.0
#4 B 1 250.0
#5 B 2 270.0
#6 B 3 290.0