【问题标题】:seperate strings in column based on count of delimiters根据分隔符的数量在列中分隔字符串
【发布时间】:2018-06-06 06:54:51
【问题描述】:

我正在尝试根据 df 中的分隔符(“_”)拆分第一列。

country_city_gender_age_name_state =c("US_Dallas_Male_23_hanes_TX","US_LosAngeles_CA",
"US_Atlanta_Female_jenny_GA","US_Orlando_kane_FL")

df = data.frame(country_city_gender_age_name_state)

第一个分隔符之前的字符串,第一个分隔符之后的第二个字符串和最后一个分隔符之前的最后一个字符串是连续的
根据上述说法
在 row_1 :所有基于 delimiter 和 no.of delimiters 拆分的字符串为 5
row_2 : 缺少分隔符 2,3,4,因此值为空,分隔符数量为 2
第 3 行:缺少分隔符 3,因此值为空,分隔符数量为 4
row_4 : 缺少分隔符 2,3 ,因此值为空,分隔符数量为 3

我已尝试使用以下代码。

df$country<- sapply(strsplit(as.character(df$country_city_gender_age_name_state),"_"), "[",1)
df$city<- sapply(strsplit(as.character(df$country_city_gender_age_name_state),"_"), "[",2)
df$gender<- sapply(strsplit(as.character(df$country_city_gender_age_name_state),"_"), "[",3)
df$age<- sapply(strsplit(as.character(df$country_city_gender_age_name_state),"_"), "[",4)
df$name<- sapply(strsplit(as.character(df$country_city_gender_age_name_state),"_"), "[",5)
df$state<- sapply(strsplit(as.character(df$country_city_gender_age_name_state), "_"), tail, 1)  

所需的输出数据框将是

country = c("US","US","US","US")
city = c("Dallas","LosAngeles","Atlanta","Orlando")
gender = c("Male","","Femal","")
age = c("23","","","")
name = c("hanes","","Jenny","kane")
state = c("TX","CA","GA","FL")

out_df = data.frame(country_city_gender_age_name_state,country,city,gender,age,name,state)

提前致谢

【问题讨论】:

  • 这很难做到。如何告诉计算机 LosAngeles 不是像“Jenny”这样的名字。
  • 可能的起始位置:library(tidyverse);df$country_city_gender_age_name_state %&gt;% map(~str_split(.,"_") %&gt;% unlist %&gt;% trimws)

标签: r


【解决方案1】:

我无法提供一个漂亮的解决方案,但这个必须有效。您总是可以找到州、国家和城市的列表,因此只需设置 ifelse 条件来比较某个值是否在其中一个列表中。对于州名,您可以处理 2 个字母的正则表达式条件或使用列表。无法在列表中找到或被正则表达式匹配的值必须是名称。

library(dplyr)
dt <- as.data.table(df)

dt$number_of_entry <- rep(1:nrow(dt))
new_dt <- dt %>% mutate(country_city_gender_age_name_state = 

strsplit(as.character(country_city_gender_age_name_state), "_")) %>% unnest(country_city_gender_age_name_state)

output <- data.frame(id = 1:nrow(dt),
                     country = rep(NA, nrow(dt)),
                     gender = rep(NA, nrow(dt)),
                     age = rep(NA, nrow(dt)),
                     name = rep(NA, nrow(dt)),
                     state = rep(NA, nrow(dt)))

number_of_entry = 1
for (i in nrow(new_dt)) {
  while (number_of_entry == new_dt$number_of_entry) {

    if (new_dt$country_city_gender_age_name_state[i] %in% list_of_countries) {
      output[number_of_entry,]$country = new_dt$country_city_gender_age_name_state[i]}
    else {

      if (new_dt$country_city_gender_age_name_state[i] %in% c("Female", "Male")) {
        output[number_of_entry,]$gender = new_dt$country_city_gender_age_name_state[i]}
      else {

        if (new_dt$country_city_gender_age_name_state[i] %in% list_of_cities) {
          output[number_of_entry,]$city = new_dt$country_city_gender_age_name_state[i]}
        else {
          if(grepl("\\d*", new_dt$country_city_gender_age_name_state[i])) {
            output[number_of_entry,]$age = new_dt$country_city_gender_age_name_state[i]}
          else {
            if (new_dt$country_city_gender_age_name_state[i] %in% list_of_states) {
              output[number_of_entry,]$state = new_dt$country_city_gender_age_name_state[i]}
            else {
              output[number_of_entry,]$name = new_dt$country_city_gender_age_name_state[i]}
            }
          }
         }
        }
      }
    }
  }
}

【讨论】:

  • 感谢KAtin,以上数据是样本数据,我们不能将性别列视为常数,它可能是邮政编码列
  • 使用正则表达式过滤即可。
【解决方案2】:

您可以尝试这样的事情,尽管它可能很难一概而论。它适用于国家、城市和州从未丢失,性别始终为“女性”或“男性”,并且字符串中唯一的数字与所需的“年龄”变量相关的情况。如果有必要,当然可以调整某些行,而且,也许其中一些行可以缩短一些。无论如何,这有帮助吗?

df = data.frame(country_city_gender_age_name_state, stringsAsFactors = F)

df$country <- sapply(strsplit(df$country_city_gender_age_name_state, "_"), "[[", 1)
df$city <- sapply(strsplit(df$country_city_gender_age_name_state, "_"), "[[", 2)
df$state <-  sapply(strsplit(df$country_city_gender_age_name_state, "_"), tail, 1)
df$gender <- ifelse(grepl("Female", df$country_city_gender_age_name_state), "Female", ifelse(grepl("Male", df$country_city_gender_age_name_state), "Male", NA))


df$age <- as.numeric(gsub("\\D", "", df$country_city_gender_age_name_state))                   

df$name <- sapply(strsplit(df$country_city_gender_age_name_state, "_"), tail, 2)[1,]
df$name <- ifelse(sapply(1:nrow(df), function(x) df[x,"name", drop = FALSE] %in%  df[x,2:6]), NA, df$name)

> df[,c(1:3,5:7,4)]
  country_city_gender_age_name_state country       city gender age  name state
1         US_Dallas_Male_23_hanes_TX      US     Dallas   Male  23 hanes    TX
2                   US_LosAngeles_CA      US LosAngeles   <NA>  NA  <NA>    CA
3         US_Atlanta_Female_jenny_GA      US    Atlanta Female  NA jenny    GA
4                 US_Orlando_kane_FL      US    Orlando   <NA>  NA  kane    FL

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-04
    • 2013-10-19
    相关资源
    最近更新 更多