簡體   English   中英

有條件地改變R中的多列

[英]Conditionally mutate multiple columns in R

我有一個數據框,其中包含j 個級別的因子列,以及長度為k 的j 個向量。 我想用后一個向量的值填充前一個數據幀中的k列,條件是因子。

簡化示例(三個級別、三個向量、兩個值):

df1 <- data.frame("Factor" = rep(c("A", "B", "C"), times = 5))
vecA <- c(1, 2)
vecB <- c(2, 1)
vecC <- c(3, 3)

這是使用嵌套 ifelse 語句的解決方案:

library(tidyverse)
df1 %>%
  mutate(V1 = ifelse(Factor == "A", vecA[1], 
                     ifelse(Factor == "B", vecB[1], vecC[1])),
         V2 = ifelse(Factor == "A", vecA[2], 
                     ifelse(Factor == "B", vecB[2], vecC[2])))

我想避免嵌套的 ifelse 語句。 理想情況下,我還想避免單獨改變每一列。

這是一個想法。 在全局環境中,獲取所有以“vec”開頭的對象,由mget() 這將創建一個列表。 對於列表中的每個元素,粘貼中間帶有“_”的數字。 然后,在向量中排列名稱以用於以下連接過程。 加入后,使用cSplit()拆分列和值。 我希望這種方法適用於您的實際情況。

library(tidyverse)
library(splitstackshape)

# Create a character vector.
mychr <- map_chr(.x = mget(ls(pattern = "vec")),
                 .f = function(x) {paste0(x, collapse = "_")})

# Remove "vec" in names.
names(mychr) <- sub(x = names(mychr), pattern = "vec", replacement = "")

#   A     B     C 
#"1_2" "2_1" "3_3"

# stack() creates a data frame. Use it in left_join().
# Then, split the column, values into two columns. You probably have more than
# two. So I decided to use cSplit() here.

left_join(df1, stack(mychr), by = c("Factor" = "ind")) %>%
cSplit(splitCols = "values", sep = "_", direction = "wide", type.convert = FALSE)

#    Factor values_1 values_2
# 1:      A        1        2
# 2:      B        2        1
# 3:      C        3        3
# 4:      A        1        2
# 5:      B        2        1
# 6:      C        3        3
# 7:      A        1        2
# 8:      B        2        1
# 9:      C        3        3
#10:      A        1        2
#11:      B        2        1
#12:      C        3        3
#13:      A        1        2
#14:      B        2        1
#15:      C        3        3

這是一個base R選項

df1[c('V1', 'V2')] <- do.call(Map, c(f = c, mget(ls(pattern="^vec[A-C]$"))))
df1
#    Factor V1 V2
#1       A  1  2
#2       B  2  1
#3       C  3  3
#4       A  1  2
#5       B  2  1
#6       C  3  3
#7       A  1  2
#8       B  2  1
#9       C  3  3
#10      A  1  2
#11      B  2  1
#12      C  3  3
#13      A  1  2
#14      B  2  1
#15      C  3  3

或者從purrr transpose

library(dplyr)
library(purrr)
mget(ls(pattern="^vec[A-C]$")) %>% 
     transpose %>% 
     setNames(c('V1', 'V2')) %>% 
     cbind(df1, .)

這是一種方法:

# modify the vectors
l <- list('A' = vecA, 'B' = vecB, 'C' = vecC)

# create df with mapping
df2 = data.frame(t(sapply(df1$Factor, function(x) l[[x]])))
colnames(df2) <- c('V1', 'V2')

new_df = cbind(df1, df2)

   Factor V1 V2
1       A  1  2
2       B  2  1
3       C  3  3
4       A  1  2
5       B  2  1
6       C  3  3
7       A  1  2
8       B  2  1
9       C  3  3
10      A  1  2
11      B  2  1
12      C  3  3
13      A  1  2
14      B  2  1
15      C  3  3

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM