【问题标题】:Replace all specific values in data.frame with values from another data.frame sequentially R将data.frame中的所有特定值依次替换为另一个data.frame中的值R
【发布时间】:2021-04-06 11:00:50
【问题描述】:

我有一个 data.frame (df1),我想为另一个 data.frame (df2) 中的每个样本包含一个最近的年龄:

df1$age <- df2$age_9[match(df1$Sample_ID, df2$Sample_ID)]

问题是df2中有9列年龄,每列表示特定检查日期的年龄(age_1是第一次就诊的年龄,age_9是第9次就诊的年龄)并且患者不做他们的所有访问。

如何从非空检查日期添加最近获得的年龄?

又名,如果 age_9 == "."代替 ”。”与 age_8 那么如果 age_8 == "."代替 ”。”与age_7 ...等

从这里:

View(df1)
Sample Age
1      50
2      .
3      .

收件人:

View(df1)
Sample Age
1      50
2      49
3      30

来自数据 df2

View(df2)
Sample Age_1 Age_2 Age_3
1      40    42    44
2      35    49    .
3      30    .     .

这是我的尝试:

df1$age[which(df1$age == ".")] <- df2$age_8[match(df1$Sample_ID, df2$Sample_ID)]

【问题讨论】:

  • 您应该stack 更新您的年龄数据集,以便获得长格式。然后您就可以使用ifelse 或者您选择的任何其他功能
  • 我不清楚格式。可能是nm1 &lt;- grep("age_\\d+", names(df2), value = TRUE); df1[nm1] &lt;- lapply(df2[nm1], function(x) x[match(df1$Sample_ID, df2$Sample_ID)])
  • @akrun 以便将 df2 的每个年龄列放入 df1 但我只想要最近年龄的一列。我稍微更新了问题以澄清
  • @SkyScraper 你试过cmets里的代码吗
  • @akrun 是的,您的代码刚刚将包含年龄信息的所有列从 df2 添加到 df1。 Onyambu 代码我无法按预期工作,但我可以再试一次

标签: r dataframe replace match


【解决方案1】:

使用base R,我们可以使用max.col返回每一行的last列索引,其中'Age'列不是.cbind用行序列返回一行/列索引,提取元素并更改'df1'中的'Age'列,其中'Age'为.

df1$Age <- ifelse(df1$Age == ".", df2[-1][cbind(seq_len(nrow(df2)), 
        max.col(df2[-1] != ".", "last"))], df1$Age)

df1 <- type.convert(df1, as.is = TRUE)

-输出

df1
#  Sample Age
#1      1  50
#2      2  49
#3      3  30

或使用tidyverse,通过重塑为'long'格式,然后在sliceing 最后一行按'Sample'分组后进行连接

library(dplyr)
library(tidyr)
df2 %>% 
    mutate(across(starts_with('Age'), as.integer)) %>%
    pivot_longer(cols = starts_with('Age'), values_drop_na = TRUE) %>%
    group_by(Sample) %>% 
    slice_tail(n = 1) %>% 
    ungroup %>% 
    select(-name) %>%
    right_join(df1) %>%
    transmute(Sample, Age = coalesce(as.integer(Age), value))

-输出

# A tibble: 3 x 2
#  Sample   Age
#   <int> <int>
#1      1    50
#2      2    49
#3      3    30

数据

df1 <- structure(list(Sample = 1:3, Age = c("50", ".", ".")), 
       class = "data.frame",
  row.names = c(NA, 
-3L))

df2 <- structure(list(Sample = 1:3, Age_1 = c(40L, 35L, 30L), Age_2 = c("42", 
"49", "."), Age_3 = c("44", ".", ".")), class = "data.frame", 
row.names = c(NA, 
-3L))

【讨论】:

  • 该死,如果使用您的数据但是当我尝试运行时:age1_age9[-1][cbind(seq_len(nrow(age1_age9)), max.col(age1_age9[-1] != ".", "last"))] 我得到错误:下标cbind(...) 是一个矩阵,它必须是逻辑类型。我正在尝试找出问题所在
  • 更新:对象的类是 "tbl_df" "tbl" "data.frame" 而不仅仅是 "data.frame" 所以使用 as.data.frame() 解决了问题
  • 第一种方案假设df1和df2的长度和顺序相同
  • 我想我会添加 right_join 的“by”运算符 (?) 但如果未提供 right_join 将自动选择要加入的变量。非常感谢
  • @SkyScraper 你可以做right_join(df1, by = "Sample"),如果列名不同,那么right_join(df1, by = c("Sample1" = "Sample2"))
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-10-29
  • 1970-01-01
  • 2015-07-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多