根据R中的条件将列的值设置为NA

时间:2018-04-06 06:50:43

标签: r

我有一个数据框,一个可重现的例子如下:

structure(list(subscriberid = c(1177460837L, 1177460837L, 1177460837L, 
1146526049L, 1146526049L, 1146526049L), variable = c("3134", 
"4550", "4550", "5160", "2530", "2530"), value = c(1, 2, 2, 1, 
2, 2), gender = c(2, 2, 2, 1, 2, 2), cwe = c(NA, 50L, 50L, NA, 
30L, 30L), hw = c(NA, 48L, 48L, NA, 26L, 26L), resp = c(NA_integer_, 
NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_
), cna = c(3L, 1L, 1L, 3L, 1L, 1L)), .Names = c("subscriberid", 
"variable", "value", "gender", "cwe", "hw", "resp", "cna"), row.names = c(4L, 
5L, 6L, 9L, 10L, 11L), class = "data.frame")

实际数据框如下所示:

   subscriberid variable value gender cwe hw resp cna
4    1177460837     3134     1      2  NA NA   NA   3
5    1177460837     4550     2      2  50 48   NA   1
6    1177460837     4550     2      2  50 48   NA   1
9    1146526049     5160     1      1  NA NA   NA   3
10   1146526049     2530     2      2  30 26   NA   1
11   1146526049     2530     2      2  30 26   NA   1

在上面的df中,第5行和第6行完全相同。从第5行开始,我想删除48和第6行我要删除50.实际上,我想连续只保留一个年龄并将另一个设置为NA。我尝试使用for循环,但是将我在两行中引用的列中的列值设置为NA。

for (i in 1:nrow(test)) {
  test$hw[i] <- ifelse(!is.na(test$cwe[i]) & !is.na(test$hw[i]), NA, test$hw[i])
}

我正在尝试设置if条件以确定两个行是否相同,然后我想迭代地从第一行中删除其中一个值并从第二行中删除另一个。

所需的输出如下:

  subscriberid variable value gender cwe hw resp cna
4    1177460837     3134     1      2  NA NA   NA   3
5    1177460837     4550     2      2  50 NA   NA   1
6    1177460837     4550     2      2  NA 48   NA   1
9    1146526049     5160     1      1  NA NA   NA   3
10   1146526049     2530     2      2  30 NA   NA   1
11   1146526049     2530     2      2  NA 26   NA   1

4 个答案:

答案 0 :(得分:2)

您可以使用which()duplicated()的组合来接收重复的行。 因为您需要更改行的两倍,所以必须创建数据帧的副本。请注意,这仅在相同的行始终连续时才有效。

dfNA <- df
dfNA$hw[which(duplicated(df))-1] <- NA
dfNA$cwe[which(duplicated(df))] <- NA

dfNA
#   subscriberid variable value gender cwe hw resp cna
#4    1177460837     3134     1      2  NA NA   NA   3
#5    1177460837     4550     2      2  50 NA   NA   1
#6    1177460837     4550     2      2  NA 48   NA   1
#9    1146526049     5160     1      1  NA NA   NA   3
#10   1146526049     2530     2      2  30 NA   NA   1
#11   1146526049     2530     2      2  NA 26   NA   1

答案 1 :(得分:1)

dplyr 包中使用潜在客户滞后

library(dplyr)

df1 %>% 
  group_by(subscriberid, variable) %>% 
  mutate(cwe = if_else(lead(cwe) == cwe, cwe, NA_integer_),
         hw = if_else(lag(hw) == hw, hw, NA_integer_)) %>% 
  ungroup()

# # A tibble: 6 x 8
#   subscriberid variable value gender   cwe    hw resp    cna
#          <int>    <int> <int>  <int> <int> <int> <lgl> <int>
# 1   1177460837     3134     1      2    NA    NA NA        3
# 2   1177460837     4550     2      2    50    NA NA        1
# 3   1177460837     4550     2      2    NA    48 NA        1
# 4   1146526049     5160     1      1    NA    NA NA        3
# 5   1146526049     2530     2      2    30    NA NA        1
# 6   1146526049     2530     2      2    NA    26 NA        1

答案 2 :(得分:1)

我开了一枪。这依赖于使用{'comment': '1', 'date_stop': '2018-03-30', 'like': '18', 'date_start': '2018-03-30', 'post_engagement': '198518', 'page_engagement': '198536', 'video_view': '198245', 'post_reaction': '268', 'post': '4'} 中的group_by来查找重复的行。此方法假定使用dplyrsubscriberidvariablevaluegender和{{1}可以可靠地将行标识为相同只有列。

因为它仅在组内操作,所以即使前一个不相同的行包含resp的相同值,它也会起作用(我确实检查过这个,但如果我是你,我也会自己确认一下) )。

cna

输出:

cwe

答案 3 :(得分:1)

可能的解决方案:

# create a logical vector indicating if current row is identical to previous one
# N.B.: do.call("paste",c(DF,sep="\r")) is used internally by "duplicated.data.frame" function
rowStrings <- do.call("paste", c(DF, sep = "\r"))
currRowIsEqualToPrev <- rowStrings[-1] == rowStrings[-length(rowStrings)]

# set first row hw = NA and second identical row cwe = NA
DF[c(FALSE,currRowIsEqualToPrev),'hw'] <- NA
DF[c(currRowIsEqualToPrev,FALSE),'cwe'] <- NA

> DF
   subscriberid variable value gender cwe hw resp cna
4    1177460837     3134     1      2  NA NA   NA   3
5    1177460837     4550     2      2  NA 48   NA   1
6    1177460837     4550     2      2  50 NA   NA   1
9    1146526049     5160     1      1  NA NA   NA   3
10   1146526049     2530     2      2  NA 26   NA   1
11   1146526049     2530     2      2  30 NA   NA   1