Есть ли функция R для нахождения значения ниже определенного значения - PullRequest
1 голос
/ 11 мая 2019

Есть ли функция R, чтобы найти значение ниже определенного значения. Пример: ниже таблица ввода. Мне нужно значение в другом столбце (COL3) ниже значения "Возраст", которое видно в столбце 2 (COL2)

COl1    COl2    
James   Age 
James   23  
Andrew  Age 
Andrew  24  

Мне нужен еще один столбец с

COl1    COl2    COl3
James   Age     23
James   23      23
Andrew  Age     24
Andrew  24      24

Ответы [ 6 ]

2 голосов
/ 11 мая 2019

Подстановка фрейма данных с помощью COL2 и соединение с исходным фреймом данных.

База

merge(df, subset(df, COl2 != "Age"), by = c("COl1"))

dplyr

library(dplyr)
df %>% 
  left_join(df %>% filter(COl2 != "Age") , by = "COl1")

sqldf

library(sqldf)
sqldf('SELECT *
      FROM df
      LEFT JOIN(SELECT *
      FROM df WHERE COl2 != "Age" )USING (COl1)')

выход

    COl1 COl2.x COl2.y
1 Andrew    Age     24
2 Andrew     24     24
3  James    Age     23
4  James     23     23

Данные

df <- structure(list(COl1 = structure(c(2L, 2L, 1L, 1L), .Label = c("Andrew", 
"James"), class = "factor"), COl2 = structure(c(3L, 1L, 3L, 2L
), .Label = c("23", "24", "Age"), class = "factor")), class = "data.frame", row.names = c(NA, 
-4L))
2 голосов
/ 11 мая 2019

С dplyr:

 df %>% 
  mutate_if(is.factor,as.character) %>% 
   mutate(COL3=ifelse(COl2=="Age",lead(COl2),COl2))
    COl1 COl2 COL3
1  James  Age   23
2  James   23   23
3 Andrew  Age   24
4 Andrew   24   24

С помощью base мы могли бы сделать следующее и удалить ненужные столбцы:

 df$COL3<-expand.grid(df[which(df$COl2=="Age")+1,])
df
    COl1 COl2 COL3.COl1 COL3.COl2
1  James  Age     James        23
2  James   23    Andrew        23
3 Andrew  Age     James        24
4 Andrew   24    Andrew        24
1 голос
/ 11 мая 2019

Решение использует от sqldf‍‍ путем присоединения фрейма данных df к себе с указанным ограничением:

library(sqldf)
result <- sqldf("SELECT df_origin.*, df_age.Col2 as Col3 FROM 
       df df_origin join
          (SELECT Col1, Col2, cast(Col2 as int) as Col2Int FROM df WHERE Col2Int > 0) df_age 
       on (df_origin.Col1 = df_age.Col1)") 
1 голос
/ 11 мая 2019

Один из способов, с помощью которого вы можете попробовать dplyr, - создать группы, используя cumsum, а затем выбрать следующее значение COl2 после "Age" в каждой группе.

library(dplyr)

df %>%
  group_by(group = cumsum(COl2 == "Age")) %>%
  mutate(Col3 = COl2[which.max(COl2 == "Age") + 1]) %>%
  ungroup() %>%
  select(-group)

 #  COl1   COl2  Col3 
 #  <chr>  <chr> <chr>
 #1 James  Age   23   
 #2 James  23    23   
 #3 Andrew Age   24   
 #4 Andrew 24    24   

Или, поскольку мы увеличиваем на "Age", мы можем выбрать второе значение из группы

library(dplyr)
df %>%
  group_by(group = cumsum(COl2 == "Age")) %>%
  mutate(Col3 = COl2[2L])

или с использованием базы R ave

with(df ,ave(COl2, cumsum(COl2 == "Age"), FUN = function(x) x[2L]))
#[1] "23" "23" "24" "24"
0 голосов
/ 19 мая 2019

в базе R:

df <- read.table(text="COl1    COl2    
James   Age 
James   23  
Andrew  Age 
Andrew  24 ", h = T)

transform(df, COl3 = ave(COl2, COl1, FUN = function(x) tail(x,1)))
#     COl1 COl2 COl3
# 1  James  Age   23
# 2  James   23   23
# 3 Andrew  Age   24
# 4 Andrew   24   24
0 голосов
/ 11 мая 2019

Использование dplyr / tidyr еще раз 1 :

library(tidyverse)

dat %>%
  mutate(COl3 = na_if(COl2, "Age")) %>%
  fill(COl3,     .direction = "up")
Данные:
#dat <- read.table(
#  text = "COl1    COl2
#  James   Age
#  James   23
#  Andrew  Age
#  Andrew  24",
#  header = T,
#  stringsAsFactors = F
#)
Вывод:
#    COl1 COl2 COl3
#1  James  Age   23
#2  James   23   23
#3 Andrew  Age   24
#4 Andrew   24   24


1 Что правильно только если !(any(is.na(dat$COl2)).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...