从多列中仅获取值(非0,非NA)

时间:2020-09-15 05:02:49

标签: r dataframe apply

这是我的数据示例:

df <- data.frame(Timing1 = c("Before", NA, 0, 0, 0, "Before"),
                 Timing2 = c(NA, "During", 0, "During", 0, NA),
                 Timing3 = c(0, NA, "After", "After", NA, 0))

我想创建一个名为Timing_combined的新列,该列仅从其他3列中获取字符串(非NA,非0)值,而忽略NA和0。

我想要的输出是这样的

 Timing1  Timing2    Timing3   Timing_combined
  Before     <NA>         0             Before
    <NA>   During      <NA>             During
       0        0     After              After
       0   During     After     During & After
       0        0      <NA>               <NA>
  Before     <NA>         0             Before

这是我到目前为止的代码:

df <- df %>% 
  mutate(Timing_combined = apply(., 1, function(x) unlist(paste(x[!is.na(x) & x != 0], sep=" & "))))

这使我靠近,但还不很远。

我遇到的问题主要是:

  1. 没有字符串(即仅NA或0s)的行将以character(0)而不是NA出现在我的数据中
  2. 具有多个定时的行作为列表c("Before", "After")存储在我的数据框中,而不是打印为"Before & After"paste()似乎不起作用,但是当我将其取出时,出现了其他问题。

我走对了吗?还是有其他更好的方法?我想避免不得不编写嵌套的for / if循环!

奖金:

我认为我不太了解R如何评估x中匿名function(x)中的apply()中的df$Timing1。功能,例如df$Timing1[1]?还是按行,例如df$Timing1[2],然后继续移动到MARGIN=1等?因为我指定了import React from "react"; import ReactDOM from "react-dom"; import store from "./configureStore"; import { Provider } from "react-redux"; import Favicon from "react-favicon"; import App from "components/App"; function renderToDom() { ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById("root") ); } renderToDom(); export { renderToDom }; ?如果有人可以愚蠢地向我解释这一点,我将不胜感激!我的实际数据集比这要复杂得多,因此我需要更好地理解这一点,以便我可以将其外推并应用到更广泛的上下文中。

谢谢!

1 个答案:

答案 0 :(得分:1)

我们可以将0的值设为NA,然后将unitena.rm = TRUE一起使用来丢弃NA的值。

library(dplyr)
library(tidyr)

df %>%
  mutate(across(.fns = ~na_if(., 0))) %>%
  unite(Timing_combined, starts_with('Timing'), 
        na.rm = TRUE, remove = FALSE, sep = ' & ')

#  Timing_combined Timing1 Timing2 Timing3
#1          Before  Before    <NA>    <NA>
#2          During    <NA>  During    <NA>
#3           After    <NA>    <NA>   After
#4  During & After    <NA>  During   After
#5                    <NA>    <NA>    <NA>
#6          Before  Before    <NA>    <NA>

如果您想使用apply

df$Timing_combined <- apply(df, 1, function(x) 
                            paste0(x[!is.na(x) & x != 0], collapse = ' & '))

apply中的匿名函数如何工作取决于您使用的MARGIN。在这里,我们传递MARGIN = 1的意思是匿名函数中的第一个迭代x将是第一行。对于第二个x,它将是第二行,依此类推。