仅使用整洁的条件,用R中的列名有条件地替换行的子集的值

时间:2018-08-16 18:28:09

标签: r dplyr mutate

我正在寻找一种方法,以有条件地替换列子集中的某些值,并使该列名保留在tidyverse中。请参见下面的示例:

wl <- data_frame(x=1:4,
  multi=c("Y","Y","Y","Y"),
  ABC=c("","Y","Y",""), 
  ABD=c("","","",""),
  ABE=c("Y","Y","","Y"))

# A tibble: 4 x 5
      x multi ABC   ABD   ABE  
  <int> <chr> <chr> <chr> <chr>
1     1 Y     ""    ""    Y    
2     2 Y     Y     ""    Y    
3     3 Y     Y     ""    ""   
4     4 Y     ""    ""    Y   

df <- wl %>% mutate_at(vars(matches("AB")),
         funs(replace(.,.=='Y',values="column name")))
# A tibble: 4 x 5
      x multi ABC         ABD   ABE        
  <int> <chr> <chr>       <chr> <chr>      
1     1 Y     ""          ""    column name
2     2 Y     column name ""    column name
3     3 Y     column name ""    ""         
4     4 Y     ""          ""    column name

,除非它是实际的列名而不是“列名”。我在这里使用了两个不同的答案,既可以对条件列进行突变(这是我进入示例的方式),又可以如何用列名替换某些值(在当前示例中未使用,但是答案是{{ 3}})。

我可以结合两个答案使它起作用:

w <- which(df=="column name",arr.ind=TRUE)
df[w] <- names(df)[w[,"col"]]                 
# A tibble: 4 x 5
      x multi ABC   ABD   ABE  
  <int> <chr> <chr> <chr> <chr>
1     1 Y     ""    ""    ABE  
2     2 Y     ABC   ""    ABE  
3     3 Y     ABC   ""    ""   
4     4 Y     ""    ""    ABE 

我承认上面的过程是完全可以运行的,但是出于纯粹的好奇心,有没有办法在没有第二块代码的情况下做到这一点?我可以插入values=步骤的replace(.,.=='Y',values="column name")部分中的某些功能来捕获列名并在单个mutate_at函数中执行整个过程吗?

4 个答案:

答案 0 :(得分:2)

您可以在mutate_at函数中进行一些tidyeval来获取列名,然后使用ifelse(或您可能想要的任何其他逻辑结构)替换某些值。

library(tidyverse)

wl %>%
  mutate_at(vars(starts_with("AB")), function(x) {
    x_var <- rlang::enquo(x)
    ifelse(x == "Y", rlang::quo_name(x_var), x)
  })
#> # A tibble: 4 x 5
#>       x multi ABC   ABD   ABE  
#>   <int> <chr> <chr> <chr> <chr>
#> 1     1 Y     ""    ""    ABE  
#> 2     2 Y     ABC   ""    ABE  
#> 3     3 Y     ABC   ""    ""   
#> 4     4 Y     ""    ""    ABE

reprex package(v0.2.0)于2018-08-16创建。

答案 1 :(得分:1)

这里是imap

的一个选项
library(purrr)
AB_cols <- grep("^AB", names(wl)) # find positions of columns that start with "AB"
wl[AB_cols] <- imap(.x = wl[AB_cols], .f = ~replace(.x, .x == "Y", .y))
wl
# A tibble: 4 x 5
#      x multi ABC   ABD   ABE  
#  <int> <chr> <chr> <chr> <chr>
#1     1 Y     ""    ""    ABE  
#2     2 Y     ABC   ""    ABE  
#3     3 Y     ABC   ""    ""   
#4     4 Y     ""    ""    ABE 

答案 2 :(得分:1)

使用tidy verse

library(dplyr)
wl %>% 
  mutate_at(vars(starts_with("AB")),
     funs(c("", deparse(substitute(.)))[(.=="Y" & !is.na(.)) + 1]))
# A tibble: 4 x 5
#     x multi ABC   ABD   ABE  
#  <int> <chr> <chr> <chr> <chr>
#1     1 Y     ""    ""    ABE  
#2     2 Y     ABC   ""    ABE  
#3     3 Y     ABC   ""    ""   
#4     4 Y     ""    ""    ABE  

使用base R

nm1 <- grep("^AB", names(wl))
i1 <- wl[,(nm1)] == "Y" & !is.na(wl[,(nm1)])
wl[,(nm1)][i1] <- names(wl)[(nm1)][col(wl[,(nm1)])][i1]
wl
# A tibble: 4 x 5
#      x multi ABC   ABD   ABE  
#  <int> <chr> <chr> <chr> <chr>
#1     1 Y     ""    ""    ABE  
#2     2 Y     ABC   ""    ABE  
#3     3 Y     ABC   ""    ""   
#4     4 Y     ""    ""    ABE  

或者我们可以通过从setdata.table进行分配来更快地做到这一点

library(data.table)
setDT(wl)
for(j in nm1) set(wl, i=which(wl[[j]] == "Y"), j=j, names(wl)[j])
wl
#   x multi ABC ABD ABE
#1: 1     Y         ABE
#2: 2     Y ABC     ABE
#3: 3     Y ABC        
#4: 4     Y         ABE

答案 3 :(得分:1)

您可以使用switchnumber1#invalid command name "*" while executing "*" invoked from within "expect "Address or name of remote host [*]? ""

   public partial class Alerts : Form
   {
      #region Private Fields

      private static BackgroundWorker bgw = new BackgroundWorker();
      private int _period = 5000;
      private System.Threading.Timer _timerThread;

      #endregion Private Fields

      #region Public Constructors

      public Alerts()
      {
         InitializeComponent();
         bgw.DoWork += bgw_DoWork;
         bgw.RunWorkerCompleted += bgw_RunWorkerCompleted;

         _timerThread = new System.Threading.Timer((o) =>
         {
            // Stop the timer;
            _timerThread.Change(-1, -1);
            // Calls UpdateAlerts() that updates a datagridview with the mysql data

            bgw.RunWorkerAsync();

            // start timer again (BeginTime, Interval)
            _timerThread.Change(_period, _period);
         }, null, 0, _period);
      }

      #endregion Public Constructors

      #region Private Methods

      private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
      {
              DataGridView1.Invoke(new System.Action(() => 
    {DataGridView1.DataSource = e.Result;}));
      }

      private void bgw_DoWork(object sender, DoWorkEventArgs e)
      {
         string constring = "datasource=localhost;port=3306;username=root;password=******";
         MySqlConnection conDataBase = new MySqlConnection(constring);
         MySqlCommand cmdDataBase = new MySqlCommand(" select * from shopmanager.alerts ;", conDataBase);

         try
         {
            conDataBase.Open();
            MySqlDataAdapter sda = new MySqlDataAdapter();
            sda.SelectCommand = cmdDataBase;
            DataTable dbdataset = new DataTable();
            sda.Fill(dbdataset);
            BindingSource bsource = new BindingSource();

            bsource.DataSource = dbdataset;
            sda.Update(dbdataset);
            e.Result = dbdataset;
         }
         catch (Exception ex)
         {
            MessageBox.Show(ex.Message);
         }
         conDataBase.Close();
      }

      #endregion Private Methods
   }