如何在r中执行条件查找?

时间:2015-06-06 14:48:29

标签: r

我使用以下两个简单的数据集:

(myData <- data.frame(ID=c(1:7, 5), Sum=c(10, 20, 30, 40, 50, 60, 700, 200)))
#   ID Sum
# 1  1  10
# 2  2  20
# 3  3  30
# 4  4  40
# 5  5  50
# 6  6  60
# 7  7 700
# 8  5 200

(myMap <- data.frame(ID=c(1:5, 7), Name=c("a", "b", "c", "d", "e", "g")))
#   ID  Name
# 1  1    a
# 2  2    b
# 3  3    c
# 4  4    d
# 5  5    e
# 6  7    g

我会用地图映射数据:

myData$Name<-myMap$Name[match(myData$ID, myMap$ID)]

但由于ID == 6没有地图条目,因此输出为:

  ID Sum Name
1  1  10    a
2  2  20    b
3  3  30    c
4  4  40    d
5  5  50    e
6  6  60 <NA>
7  7 700    g
8  5 200    e

我现在要做的是:在NameNA的记录中,Name应该变为ID。 我的尝试:

myData$Dummy<-ifelse( is.na(myData$Name),myData$ID, myData$Name)

for (i in 1:length(myData$Name) )
  if (is.na(myData$Name[i])) 
  {
    x <- myData$ID[i]
    # print(x)
    myData$Name[i]<- as.factor(x)
    print(myData$Name[i])
  }

错了。你能给我一个提示吗?

2 个答案:

答案 0 :(得分:5)

事实上,你认为的角色是真正的一个因素。在创建数据框时使用stringsAsFactors=FALSE,或者在操作数据时需要考虑它。我在下面提供了dplyr +管道和基础R解决方案。请注意使用left_joindplyr)或merge(基数)与您的子集&amp;匹配:

library(dplyr)

myData <- read.csv(text="ID;Sum
1;10
2;20
3;30
4;40
5;50
6;60
7;700
5;200", sep=";")

myMap <- read.csv(text="ID;Name
1;a
2;b
3;c
4;d
5;e
7;g", sep=";")

# dplyr -------------------------------------------------------------------

myData %>%
  left_join(myMap) %>%
  mutate(Name=as.character(Name),
         Name=ifelse(is.na(Name), ID, Name)) -> dplyr_myData

## Joining by: "ID"

dplyr_myData

##   ID Sum Name
## 1  1  10    a
## 2  2  20    b
## 3  3  30    c
## 4  4  40    d
## 5  5  50    e
## 6  6  60    6
## 7  7 700    g
## 8  5 200    e

# base --------------------------------------------------------------------

base_myData <- merge(myData, myMap, all.x=TRUE)
base_myData$Name <- as.character(base_myData$Name)
base_myData$Name <- ifelse(is.na(base_myData$Name),
                           base_myData$ID, base_myData$Name)

base_myData

##   ID Sum Name
## 1  1  10    a
## 2  2  20    b
## 3  3  30    c
## 4  4  40    d
## 5  5  50    e
## 6  5 200    e
## 7  6  60    6
## 8  7 700    g

答案 1 :(得分:2)

使用data.table

的选项
library(data.table)#1.9.5+
setkey(setDT(myData), ID)[myMap, Name:=i.Name][is.na(Name),
              Name:= as.character(ID)]
#   ID Sum Name
#1:  1  10    a
#2:  2  20    b
#3:  3  30    c
#4:  4  40    d
#5:  5  50    e
#6:  5 200    e
#7:  6  60    6
#8:  7 700    g

注意:正如@Arun所评论的,在devel版本v1.9.5中,我们也可以将密钥设置为setDT内的参数,即setDT(myData, key='ID')