我有一个这样的数据框,其中第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的新手,在如何实现我想要的结果方面苦苦挣扎。
答案 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_number
和country_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)
我们可以将replace
与na.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