我有一个包含几行的数据集。
x1 x2 x3 x4 x5 y1 y2 y3 y4 y5
1 3 2 1 5 0.2 0.1 0.1 0.4 0.2
1 2 4 2 4 -1 -1 -1 -1 -1
4 4 1 2 4 0.2 0.2 0.3 0.1 0.9
-1
实际上只是一个任意值,表示没有东西。
我想将-1
列中的y
切换为x
列:
x1 x2 x3 x4 x5 y1 y2 y3 y4 y5
1 3 2 1 5 0.2 0.1 0.1 0.4 0.2
-1 -1 -1 -1 -1 1 2 4 2 4 ###Changed row
4 4 1 2 4 0.2 0.2 0.3 0.1 0.9
这只是一个示例数据集;问题是,我有超过30个数据集,每个数据集都有1000多行数据,这些事情发生在几个地方。我知道有一种方法可以通过切断整个数据集和切换值来实现它,但我想知道是否有更优雅的方法来处理大型数据集,例如使用for循环?
答案 0 :(得分:1)
另一种解决方案:
library(dplyr)
#Example dataframe
df <- data.frame(
matrix(round(runif(15,min = 0,max=5),digits = 0),ncol = 5),
matrix(round(runif(15,min = 0,max=1),digits = 1),ncol = 5,dimnames = list(NULL,paste0('y',1:5)))
)
df[2,6:10] <- -1
switcher_function <- function(d){
d <- data.frame(t(d))
df.y <- d %>% select(contains('y'))
df.x <- d %>% select(contains('x'))
if(sum(df.y)==-1*ncol(df.y)){
return(as.numeric(cbind(df.y[1,],df.x[1,])))
}else{
return(as.numeric(cbind(df.x[1,],df.y[1,])))
}
}
want <- t(apply(X = df,MARGIN = 1,FUN = switcher_function))
答案 1 :(得分:0)
这是一个使用基数R的想法,假设你只有2组不同的列(x和y),那么,
ind1 <- t(apply(df2, 1, function(i)mapply(function(x, y)
replace(x, all(y == -1), y), i[grepl('x', names(i))], i[grepl('y', names(i))])))
ind2 <- t(apply(df2, 1, function(i)mapply(function(x, y)
replace(x, all(x == -1), y), i[grepl('y', names(i))], i[grepl('x', names(i))])))
final_df <- as.data.frame(cbind(ind1, ind2))
final_df
# x1 x2 x3 x4 x5 y1 y2 y3 y4 y5
#1 1 3 2 1 5 0.2 0.1 0.1 0.4 0.2
#2 -1 -1 -1 -1 -1 1.0 2.0 4.0 2.0 4.0
#3 4 4 1 2 4 0.2 0.2 0.3 0.1 0.9
答案 2 :(得分:0)
In tidy data format,您的表格如下:
i x y
1 1 1 0.2
2 1 1 -1.0
3 1 4 0.2
4 2 3 0.1
5 2 2 -1.0
6 2 4 0.2
7 3 2 0.1
8 3 4 -1.0
9 3 1 0.3
10 4 1 0.4
11 4 2 -1.0
12 4 2 0.1
13 5 5 0.2
14 5 4 -1.0
15 5 4 0.9
以这种格式给出,交换y
为负的单元格是微不足道的(...):
mutate_when(df, y < 0, x = y, y = x)
这会将{dplyr>扩展名mutate_when
)与its code available as a Github Gist一起使用。
或者你可以只使用
do(tibble(x = ifelse(.$y < 0, .$y, .$x),
y = ifelse(.$y < 0, .$x, .$y),
i = .$i))
这是使用同名包中的tibble
和do
。可能有更好的方法 - 我只是不知道。
...但是让你的表格变得整洁,并且在转换之后,退出整洁的格式会有点复杂。这是整理数据的转变:
tidy_df = df %>%
gather(name, value) %>%
mutate(i = as.integer(sub('x|y', '', name)),
name = sub('\\d', '', name)) %>%
group_by(name, i) %>%
mutate(row = row_number()) %>%
ungroup() %>%
spread(name, value)
(这会添加一个额外的列来保留原始表中的行索引,然后将其转换回来。如果不需要,那么索引也不会。)
现在我们可以执行交换......
tidy_df_swapped = tidy_df %>%
mutate_when(y < 0, x = y, y = x)
之后转换回来看起来像这样:
df_swapped = tidy_df_swapped %>%
gather(name, value, -i, -row) %>%
mutate(name = paste0(name, i)) %>%
select(-i) %>%
spread(name, value) %>%
select(-row)
答案 3 :(得分:0)
这是一个矩阵解决方案,因为它没有指定数据的存储方式。我还将-1
更改为NA
,因为它被声明是一个任意选择
m1 <- structure(c(1, 1, 4, 3, 2, 4, 2, 4, 1, 1, 2, 2, 5, 4, 4, 0.2, NA, 0.2, 0.1, NA, 0.2, 0.1, NA, 0.3, 0.4, 2, NA, 0.2, NA, NA),
.Dim = c(3L, 10L),
.Dimnames = list(NULL, c("x1", "x2", "x3", "x4", "x5", "y1", "y2", "y3", "y4", "y5")))
ind <- is.na(m1[, paste0("y", 1:5)])
m1[ind] <- c(tail(m1[ind], length(m1[ind])/2), head(m1[ind], length(m1[ind])/2))
提供一些速度比较(并节省微秒!)
Unit: microseconds
min lq mean median uq max neval
matrix 47.940 64.8710 89.9407 86.939 98.734 165.126 100
final_df 704.258 742.3055 986.9160 791.767 1057.909 4310.011 100
want 3647.605 3982.4225 5184.6407 4410.836 6450.177 15161.132 100
在第二步中可能有一种更优雅的方式来交换阵列,但它是我现在所拥有的。