R数据操作。查找列值并进行操作

时间:2016-12-25 04:17:11

标签: r data-manipulation

我有一个这样的数据框,其中第1列有不同的值,以国家/地区结束。

Col1     col2  Col3  col4 
    A        0    0     1
    B        1    0     3 
    c        4    0     6
    D        5    6     7
    China    na   na    na 
    A        0    1     3
    B        2    4     5
    C        3    5     6
    D        1     2    3 
    E        5    3     3 
    England  na    na   na 

我希望实现以下内容,因此我需要创建一个操作国家/地区名称的新列,直到匹配国家/地区名称的行。

Col1     col2  Col3  col4 col5
A        0    0     1     China 
B        1    0     3     china 
c        4    0     6     china 
D        5    6     7     china 
China    na   na    na    china 
A        0    1     3     England
B        2    4     5     England
C        3    5     6     England
D        1    2    3      England 
E        5    3     3     England
England  na    na   na    England

...加上我还有其他40个国家可以合作。我是R的新手,在如何实现我想要的结果方面苦苦挣扎。

4 个答案:

答案 0 :(得分:3)

首先创建数据结构(将来你应该提供在你的问题中执行此操作的代码)。

exd <- read.table(text = "Col1     col2  Col3  col4 
    A        0    0     1
    B        1    0     3 
    c        4    0     6
    D        5    6     7
    China    NA   NA    NA 
    A        0    1     3
    B        2    4     5
    C        3    5     6
    D        1     2    3 
    E        5    3     3 
    England  NA    NA   NA", header = TRUE)

接下来,确定哪些行是国家/地区边界,并提取国家/地区名称

country_boundary <- nchar(as.character(exd$Col1)) > 1
country_names <- exd$Col1[country_boundary]

然后为每个国家生成代码,换一个。

country_number <- c(0, cumsum(country_boundary)[-nrow(exd)])

最后,使用country_numbercountry_names向量创建国家/地区ID列。

exd <- data.frame(exd,
                  Col5 = factor(country_number,
                                labels = country_names))

您可能希望删除(现在是多余的)边界行:

exd <- exd[!country_boundary, ]
exd
#    Col1 col2 Col3 col4    Col5
# 1     A    0    0    1   China
# 2     B    1    0    3   China
# 3     c    4    0    6   China
# 4     D    5    6    7   China
# 6     A    0    1    3 England
# 7     B    2    4    5 England
# 8     C    3    5    6 England
# 9     D    1    2    3 England
# 10    E    5    3    3 England

答案 1 :(得分:1)

另一种hacky方法:使用Col1作为起点,使所有观察都具有单个字符NA。然后用最后一个值填充NA

library(zoo)

df$col5 = df$Col1
df$col5 = ifelse(nchar(as.character(df$col5)) > 1, as.character(df$col5), NA)
df$col5 = na.locf(as.character(df$col5), fromLast = TRUE)

答案 2 :(得分:1)

tidyverse选项:

library(tidyverse)

       # convert all to appropriate types
df %>% mutate_all(as.character) %>% type_convert(na = 'na') %>% 
    # add column with Col1 value if a row only has one non-NA value, else NA
    mutate(country = ifelse(rowSums(!is.na(.)) == 1, Col1, NA)) %>% 
    fill(country, .direction = 'up') %>%    # replace NAs upwards with last non-NA value
    filter(complete.cases(.))    # subset to rows with no NAs

##   Col1 col2 Col3 col4 country
## 1    A    0    0    1   China
## 2    B    1    0    3   China
## 3    c    4    0    6   China
## 4    D    5    6    7   China
## 5    A    0    1    3 England
## 6    B    2    4    5 England
## 7    C    3    5    6 England
## 8    D    1    2    3 England
## 9    E    5    3    3 England

答案 3 :(得分:0)

我们可以将replacena.locf

一起使用
library(zoo)
df1$Col5 <- with(df1, na.locf(replace(Col1, nchar(Col1)==1, NA), fromLast=TRUE))
df1$Cpl5
#[1] "China"   "China"   "China"   "China"   "China"   "England" "England"
#[8] "England" "England" "England" "England"

或另一个选项是data.table

library(data.table)
setDT(df1)[, Col5 := Col1[.N], cumsum(shift(nchar(Col1)>1, fill = TRUE))]
df1
#       Col1 col2 Col3 col4    Col5
# 1:       A    0    0    1   China
# 2:       B    1    0    3   China
# 3:       c    4    0    6   China
# 4:       D    5    6    7   China
# 5:   China   na   na   na   China
# 6:       A    0    1    3 England
# 7:       B    2    4    5 England
# 8:       C    3    5    6 England
# 9:       D    1    2    3 England
#10:       E    5    3    3 England
#11: England   na   na   na England