我有一个数据框,其中每一行代表每个人的交互数据。
This should be Uppercase
每个人可以进行以下一种或多种互动:
actions = read.table('C:/Users/Desktop/actions.csv', header = F, sep = ',', na.strings = '', stringsAsFactors = F)
每个人记录的动作时长可能会有所不同,如下所示:
eat, sleep, walk, jump, hop, wake, run
为使长度相等,我在末尾添加了NA填充:
P1: eat, sleep, sleep, sleep
P2: wake, walk, eat, walk, walk, jump, jump, run, run
P3: wake, eat, walk, jump, run, sleep
现在,我的要求是更新每人条目(行数据),以便没有两个连续的条目重复。维持订单非常重要。我需要的输出是:
P1: eat, sleep, sleep, sleep, NA, NA, NA, NA, NA
P2: wake, walk, eat, walk, walk, jump, jump, run, run
P3: wake, eat, walk, jump, run, sleep, NA, NA, NA
默认情况下,列名称为V1,V2,V3...。Vn其中
P1: eat, sleep, NA, NA, NA, NA, NA, NA, NA
P2: wake, walk, eat, walk, jump, run, NA, NA, NA
P3: wake, eat, walk, jump, run, sleep, NA, NA, NA
在上面的示例中,P2具有最大长度;所以n =9。所以上例中的总列来自V1-V9。
的输出
n = maximum length of interactions string
以下问题:Removing Only Adjacent Duplicates in Data Frame in R与我的有点类似,但是有几个区别。即使通过合并上述问题的代码,我也无法解决我的问题。
任何对此的建议将不胜感激!
答案 0 :(得分:3)
library(tidyverse)
read.csv(text=gsub(" +", "", "P1, eat, sleep, sleep, sleep, NA, NA, NA, NA, NA
P2, wake, walk, eat, walk, walk, jump, jump, run, run
P3, wake, eat, walk, jump, run, sleep, NA, NA, NA"),
header = FALSE, stringsAsFactors = FALSE) %>%
setNames(c("person", sprintf("i%s", 1:9))) %>% tbl_df() -> xdf
de_dup <- function(x) {
# remove consecutive dups and keep order
interactions <- rle(unlist(x, use.names = FALSE)[-1])$values
# fill in NAs
interactions <- c(interactions, rep(NA_character_, length(x[-1])-length(interactions)))
# return a data frame
as.data.frame(as.list(setNames(c(x[1], interactions), names(x))), stringsAsFactors=FALSE)
}
rowwise(xdf) %>%
do(de_dup(.)) %>%
ungroup()
## # A tibble: 3 x 10
## person i1 i2 i3 i4 i5 i6 i7 i8 i9
## * <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
## 1 P1 eat sleep NA NA NA NA NA NA NA
## 2 P2 wake walk eat walk jump run NA NA NA
## 3 P3 wake eat walk jump run sleep NA NA NA
请求的博览会
由于dups是跨列的,所以最直接的方法(不一定是最快或最少的内存/ CPU密集型)是逐行重新创建数据帧。
rowwise()
是一项tidyverse
函数,可将数据帧按行分成组do()
提取每一行,并将其传递给我们创建的函数,以使代码更具可读性和可更新性(不同于将内嵌括号{}
的疯狂与分号混淆)与换行符)。 .
==整个行x
中的de_dup()
参数将是一个命名列表(请阅读do
上的文档)unlist()
转换为向量rle
函数,但不传递给人的第一个元素。这不是完全必要的(人将是唯一的),但它具有注意逻辑,因为您知道您正在与人进行交互。查看rle(c("a", "a", "b", "c", "c", "c", "d))
的输出以了解其功能。它代表游程长度编码,专为满足您的需求而构建rle
的返回值包含一个values
元素,该元素具有不包含NA
的重复数据删除元素。NA
。有很多方法可以做到这一点。我喜欢这种方式。do()
上的文档),以便我们创建一个命名的字符向量并将其转换为数据框do()
的末尾,我们仍然有按行分组的数据帧,因此我们需要对其进行取消分组答案 1 :(得分:1)
这是使用基数R的一种简单方法。我只创建了一个函数,该函数将用NA
替换连续的重复项,并按所需顺序重新排列新行-
# function to check consecutive duplicates
ccd <- function(x) {
# first value can never be duplicate so initiating to 0
test <- c(0, sapply(1:(length(x)-1), function(i) anyDuplicated(x[i:(i+1)])))
x[test > 0] <- NA_character_
x[order(test)]
}
# Original df from dput
> df
V1 V2 V3 V4 V5 V6 V7 V8 V9
1 S C R S C R S C R
2 C C C <NA> <NA> <NA> <NA> <NA> <NA>
3 R R R R R <NA> <NA> <NA> <NA>
for(r in 1:nrow(df)) {
df[r, ] <- ccd(as.character(df[r, ]))
}
> df
V1 V2 V3 V4 V5 V6 V7 V8 V9
1 S C R S C R S C R
2 C <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA>
3 R <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA>
对于帖子中的演示示例-
df <- read.csv(
text=gsub(" +", "", "P1, eat, sleep, sleep, sleep, NA, NA, NA, NA, NA
P2, wake, walk, eat, walk, walk, jump, jump, run, run
P3, wake, eat, walk, jump, run, sleep, NA, NA, NA"),
header = FALSE, stringsAsFactors = FALSE)[, -1]
> df
V2 V3 V4 V5 V6 V7 V8 V9 V10
1 eat sleep sleep sleep <NA> <NA> <NA> <NA> <NA>
2 wake walk eat walk walk jump jump run run
3 wake eat walk jump run sleep <NA> <NA> <NA>
for(r in 1:nrow(df)) {
df[r, ] <- ccd(as.character(df[r, ]))
}
> df
V2 V3 V4 V5 V6 V7 V8 V9 V10
1 eat sleep <NA> <NA> <NA> <NA> <NA> <NA> <NA>
2 wake walk eat walk jump run <NA> <NA> <NA>
3 wake eat walk jump run sleep <NA> <NA> <NA>
答案 2 :(得分:1)
dplyr
,reshape2
和基数R的组合。首先,它标识所需的重复项并将其替换为NA。然后,将非NA值向左移动。
as.data.frame(t(apply(df %>%
gather(var, val, -V1) %>%
group_by(V1) %>%
mutate(val2 = ifelse(val == lag(val), NA, val),
val2 = ifelse(var == "V2", paste(val), val2)) %>%
dcast(V1~var, value.var = "val2"), 1, function(x) c(x[!is.na(x)], x[is.na(x)]))))
V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
1 P1 eat sleep <NA> <NA> <NA> <NA> <NA> <NA> <NA>
2 P2 wake walk eat walk jump run <NA> <NA> <NA>
3 P3 wake eat walk jump run sleep <NA> <NA> <NA>
数据(使用@Shree中的代码):
df <- read.csv(text = gsub(" +", "", "P1, eat, sleep, sleep, sleep, NA, NA, NA, NA, NA
P2, wake, walk, eat, walk, walk, jump, jump, run, run
P3, wake, eat, walk, jump, run, sleep, NA, NA, NA"),
header = FALSE, stringsAsFactors = FALSE)