R根据列值编辑数据框
R editing dataframe based on column value
假设我有一个 table 大约 100 万行,格式如下:
id paid_2000 paid_2001 paid_2002 paid_2003 censor_yr
1 10 20 10 20 2001
2 15 25 15 15 2003
在付费年份大于或等于审查年份的情况下,将每个观测值设置为 NA 的有效方法是什么?特别是,我希望 table 看起来像这样:
id paid_2000 paid_2001 paid_2002 paid_2003 censor_yr
1 10 NA NA NA 2001
2 15 25 15 NA 2003
我们为 'paid' ('pi') 的列创建索引,使用 'pi' 对列进行子集化,通过比较列中的年份子字符串创建逻辑值矩阵'paid' 列的名称与 'censor_yr' 列的名称并将其分配给 NA。
pi <- grep("paid", names(df1))
df1[pi][matrix(as.numeric(sub(".*_", "", names(df1)[pi]))[col(df1[pi])] >=
df1$censor_yr, nrow=2)] <- NA
df1
# id paid_2000 paid_2001 paid_2002 paid_2003 censor_yr
#1 1 10 NA NA NA 2001
#2 2 15 25 15 NA 2003
或者我们可以在 data.table
set
中执行此操作,这样效率会更高。从'paid'列名的names
中获取年份子串,转换为data.table
(setDT(df1)
),循环遍历'pi'和[=13中的列=] 满足'i'.
条件的NA值
library(data.table)
nm1 <- as.numeric(sub(".*_", "", names(df1)[pi]))
setDT(df1)
for(j in seq_along(pi)){
set(df1, i = which(nm1[j] >= df1$censor_yr), j= pi[j], value = NA)
}
使用dplyr
:
library(dplyr)
df %>%
gather(paid_yr, value, grep("paid", names(.))) %>%
mutate(value = ifelse(as.numeric(gsub(".*_", "", paid_yr)) >= censor_yr,
NA, value)) %>%
spread(paid_yr, value)
在底部扔一个 %>% select
链子以将 censor_yr
移回末端。
如果您愿意,可以解释它是如何工作的。可能比 akrun 的答案更容易阅读,也可能不更容易阅读。
假设我有一个 table 大约 100 万行,格式如下:
id paid_2000 paid_2001 paid_2002 paid_2003 censor_yr
1 10 20 10 20 2001
2 15 25 15 15 2003
在付费年份大于或等于审查年份的情况下,将每个观测值设置为 NA 的有效方法是什么?特别是,我希望 table 看起来像这样:
id paid_2000 paid_2001 paid_2002 paid_2003 censor_yr
1 10 NA NA NA 2001
2 15 25 15 NA 2003
我们为 'paid' ('pi') 的列创建索引,使用 'pi' 对列进行子集化,通过比较列中的年份子字符串创建逻辑值矩阵'paid' 列的名称与 'censor_yr' 列的名称并将其分配给 NA。
pi <- grep("paid", names(df1))
df1[pi][matrix(as.numeric(sub(".*_", "", names(df1)[pi]))[col(df1[pi])] >=
df1$censor_yr, nrow=2)] <- NA
df1
# id paid_2000 paid_2001 paid_2002 paid_2003 censor_yr
#1 1 10 NA NA NA 2001
#2 2 15 25 15 NA 2003
或者我们可以在 data.table
set
中执行此操作,这样效率会更高。从'paid'列名的names
中获取年份子串,转换为data.table
(setDT(df1)
),循环遍历'pi'和[=13中的列=] 满足'i'.
library(data.table)
nm1 <- as.numeric(sub(".*_", "", names(df1)[pi]))
setDT(df1)
for(j in seq_along(pi)){
set(df1, i = which(nm1[j] >= df1$censor_yr), j= pi[j], value = NA)
}
使用dplyr
:
library(dplyr)
df %>%
gather(paid_yr, value, grep("paid", names(.))) %>%
mutate(value = ifelse(as.numeric(gsub(".*_", "", paid_yr)) >= censor_yr,
NA, value)) %>%
spread(paid_yr, value)
在底部扔一个 %>% select
链子以将 censor_yr
移回末端。
如果您愿意,可以解释它是如何工作的。可能比 akrun 的答案更容易阅读,也可能不更容易阅读。