如果 - 然后有多个字符和条件

问题描述 投票:0回答:2

我希望有人可以帮助我,因为我目前使用grepl的方法并没有导致任何有效的方法

我有几个类别(存储为字符)。我现在想要构建一个变量,它为不同的类别采用不同的值。

数据如下所示

category                                 

Candidate Biography                        
Candidate Biography                         
Candidate Biography                         
Candidate Biography, Campaign Finance       
Justice, Candidate Biography, Economy       
Candidate Biography, Jobs                   
Economy, Education, Candidate Biography    
Economy, Civil Rights, Candidate Biography

现在我想根据类别创建可以采用不同值的新变量,如下所示

category                                 CandBio   Economy  CivilRights   Family
Candidate Biography                         1         0          0           0
Candidate Biography                         1         0          0           0
Candidate Biography                         1         0          0           0
Candidate Biography, Campaign Finance       0.5       0.5        0           0
Justice, Candidate Biography, Economy       0.33      0.33       0.33        0
Candidate Biography, Jobs                   0.5       0.5        0           0
Economy, Education, Candidate Biography     0.33      0.33       0           0.33
Economy, Civil Rights, Candidate Biography  0.33      0.33       0.33        0

每个类别对每个变量都有一个特定因子(并且可以加载到不同的类别)。例如。 “Candidate Biography,Campaign Finance”每个都加载了CandBio和Economy 0.5。对于数据集内的许多观察,类别重新出现。 (总共49k obs,120个不同的类别需要汇总到10个变量中,如示例中的CandBio,Economy,CivilRights等)

我首先尝试将ifelse和grepl结合起来,但我意识到grepl对顺序非常敏感,并且我可以根据我构造ifelse的方式为每个类别进行错误分类。此外,我试图获得具有相似数字的所有类别术语的vactors,然后在grepl函数中包含向量,但这也没有用。

所以我正在寻找任何解决方案,帮助我根据类别文本将权重分配给变量。

我希望我能清楚地描述我的问题,我期待着任何帮助,非常感谢!非常感谢!

编辑:到目前为止,我尝试过这种方式,但没有成功:

clintontvad$CandidateBiography <- ifelse(ifelse(grepl("Candidate Biography", clintontvad$subjects),1,
                                                ifelse(grepl("Candidate Biography, Marriage, Gays and Lesbians, Civil Rights, Immigration, Trade, Energy, Workers", clintontvad$subjects), 0.125, 
                                                ifelse(grepl("Candidate Biography, Terrorism, Islam, Foreign Policy, Nuclear, Iran", clintontvad$subjects),0.17,
                                                ifelse(grepl("Children, Candidate Biography, Families, Education, Debt, Economy, Jobs", clintontvad$subjects),0.17,
                                                       ifelse(grepl("Candidate Biography, Children, Education, Health Care, Women", clintontvad$subjects), 0.2,
                                                              ifelse(grepl("Candidate Biography, Civil Rights, Islam, Gays and Lesbians, Women", clintontvad$subjects), 0.2,
                                                                     ifelse(grepl("Candidate Biography, Economy, Election, Children, Families", clintontvad$subjects), 0.2,
                                                                            ifelse(grepl("Children, Education, Women, Economy, Families", clintontvad$subjects), 0.2,
                                                                                   ifelse(grepl("Job Accomplishments, Abortion, Women, Health Care, Climate Change, Marriage", clintontvad$subjects), 0.2,
                                                                                          ifelse(grepl("Women, Civil Rights, Gays and Lesbians, Foreign Policy, Canddate Biography", clintontvad$subjects), 0.25, 
                                                                                                 ifelse(grepl("Poverty, Health Care, Candidate Biography, Terrorism", clintontvad$subjects), 0.25,
                                                                                                        ifelse(grepl("Job Accomplishments, Foreign Policy, Health Care, Children", clintontvad$subjects), 0.25,
                                                                                                               ifelse(grepl("Foreign Policy, Terrorism, Candidate Biography", clintontvad$subjects),0.25,
                                                                                                                      ifelse(grepl("Ethics, Terrorism, Candidate Biography", clintontvad$subjects),0.25, 0)))))))))))))
r if-statement character grepl
2个回答
1
投票

如果我正确理解了您的示例,那么新变量的权重取决于每行中的类别数。在这种情况下,您可以使用两步法。首先创建新变量,然后除以匹配类别的数量。

d <- data.frame(category = c("Candidate Biography", "Candidate Biography", "Candidate Biography", 
                             "Candidate Biography, Campaign Finance", 
                             "Justice, Candidate Biography, Economy", "Candidate Biography, Jobs", 
                             "Economy, Education, Candidate Biography", 
                             "Economy, Civil Rights, Candidate Biography"))

# create a list with all your new variables and their respective categories
categories <- list(
  CandBio = c("Candidate Biography"),   
  Economy = c("Campaign Finance", "Economy", "Jobs"), 
  CivilRights = c("Justice", "Civil Rights"), 
  Family = c("Education")
  )

# create the new variables
for (i in seq_along(categories)) {
  d[names(categories)[i]] <- grepl(paste0(categories[[i]], collapse = "|"), d[, "category"])
}

# divide by number of matched categories
d[, -1] <- d[, -1]/rowSums(d[, -1])

d
                                    category   CandBio   Economy CivilRights    Family
1                        Candidate Biography 1.0000000 0.0000000   0.0000000 0.0000000
2                        Candidate Biography 1.0000000 0.0000000   0.0000000 0.0000000
3                        Candidate Biography 1.0000000 0.0000000   0.0000000 0.0000000
4      Candidate Biography, Campaign Finance 0.5000000 0.5000000   0.0000000 0.0000000
5      Justice, Candidate Biography, Economy 0.3333333 0.3333333   0.3333333 0.0000000
6                  Candidate Biography, Jobs 0.5000000 0.5000000   0.0000000 0.0000000
7    Economy, Education, Candidate Biography 0.3333333 0.3333333   0.0000000 0.3333333
8 Economy, Civil Rights, Candidate Biography 0.3333333 0.3333333   0.3333333 0.0000000

0
投票

只要我理解正确,这是一种方法。您需要为您的类别添加匹配矢量,并且您需要密切关注案例或者您是否有任何特殊字符。但这应该让你开始。如果您有任何问题,请告诉我。此外,事后看来,我将太多的东西命名为“类别”,但你应该明白这一点。 category1 23指的是构成你更广泛群体的任何东西(例如,EconomyCivilRights)。最后,如果这很慢,使用stringi而不是grepl的函数可能要快得多。如果此基本解决方案太慢,我可以发布编辑。

# Example dataframe
df <- data.frame(category = c("cat 1a",
                        "cat 1a",
                        "cat 1a",
                        "cat 1a, cat 2a",
                        "cat 3a, cat 1a, cat 2b",
                        "cat 1a, cat 2c"),
                 stringsAsFactors = F)

# Create a list with strings split based on the comma
string_list <- strsplit(df$category, split = ",", fixed = TRUE)

# Pre defined categories
category1 <- c("cat 1a", "cat 1b", "cat 1c")
category2 <- c("cat 2a", "cat 2b", "cat 2c")
category3 <- c("cat 3a", "cat 3b", "cat 3c")

# Create new columns based on your categories
df$Category_1 <- sapply(1:length(string_list) , function (x) any(grepl(paste(category1, collapse = "|"), unlist(string_list[x]))) / 
                          length(unlist(string_list[x])))
df$Category_2 <- sapply(1:length(string_list) , function (x) any(grepl(paste(category2, collapse = "|"), unlist(string_list[x]))) / 
                          length(unlist(string_list[x])))
df$Category_3 <- sapply(1:length(string_list) , function (x) any(grepl(paste(category3, collapse = "|"), unlist(string_list[x]))) / 
                          length(unlist(string_list[x])))

df
                category Category_1 Category_2 Category_3
1                 cat 1a  1.0000000  0.0000000  0.0000000
2                 cat 1a  1.0000000  0.0000000  0.0000000
3                 cat 1a  1.0000000  0.0000000  0.0000000
4         cat 1a, cat 2a  0.5000000  0.5000000  0.0000000
5 cat 3a, cat 1a, cat 2b  0.3333333  0.3333333  0.3333333
6         cat 1a, cat 2c  0.5000000  0.5000000  0.0000000

编辑:使用@ Gilean0709友好提供的数据(和stringi,使其更快),这是一个udpdate:

# Example dataframe
df <- data.frame(category = c("Candidate Biography", "Candidate Biography", "Candidate Biography", 
                             "Candidate Biography, Campaign Finance", 
                             "Justice, Candidate Biography, Economy", "Candidate Biography, Jobs", 
                             "Economy, Education, Candidate Biography", 
                             "Economy, Civil Rights, Candidate Biography"), stringsAsFactors = F)


# Create a list with strings split based on the comma
string_list <- strsplit(df$category, split = ",", fixed = TRUE)

library(stringi)

# Pre defined categories
CandBio <- paste(c("Candidate Biography"), collapse = "|")
Economy <- paste(c("Campaign Finance", "Economy", "Jobs"), collapse = "|")
CivilRights <- paste(c("Justice", "Civil Rights"), collapse = "|")
Family <- paste(c("Education"), collapse = "|")

# Create new columns based on your categories
df$CandBio <- sapply(1:length(string_list), function (x) any(stri_detect_regex(unlist(string_list[x]), CandBio)) / 
                          length(unlist(string_list[x])))
df$Economy <- sapply(1:length(string_list), function (x) any(stri_detect_regex(unlist(string_list[x]), Economy)) / 
                          length(unlist(string_list[x])))
df$CivilRights <- sapply(1:length(string_list), function (x) any(stri_detect_regex(unlist(string_list[x]), CivilRights)) / 
                          length(unlist(string_list[x])))
df$Family <- sapply(1:length(string_list), function (x) any(stri_detect_regex(unlist(string_list[x]), Family)) / 
                          length(unlist(string_list[x])))

df %>%
  mutate_if(is.numeric, round, digits = 2)
                                    category CandBio Economy CivilRights Family
1                        Candidate Biography    1.00    0.00        0.00   0.00
2                        Candidate Biography    1.00    0.00        0.00   0.00
3                        Candidate Biography    1.00    0.00        0.00   0.00
4      Candidate Biography, Campaign Finance    0.50    0.50        0.00   0.00
5      Justice, Candidate Biography, Economy    0.33    0.33        0.33   0.00
6                  Candidate Biography, Jobs    0.50    0.50        0.00   0.00
7    Economy, Education, Candidate Biography    0.33    0.33        0.00   0.33
8 Economy, Civil Rights, Candidate Biography    0.33    0.33        0.33   0.00
© www.soinside.com 2019 - 2024. All rights reserved.