Update Rows of Data Frame in R

Update rows of data frame in R

We can use match to get the row index. Using that index to subset the rows, we replace the 2nd and 3rd columns of the first dataset with the corresponding columns of second dataset.

ind <- match(df2$ID, df1$ID)
df1[ind, 2:3] <- df2[2:3]
df1
# ID Measurement1 Measurement2
#1 1 45 104
#2 2 10 11
#3 3 23 99
#4 4 21 22

Or we can use data.table to join the dataset on the 'ID' column (after converting the first dataset to 'data.table' i.e. setDT(df1)), and assign the 'Cols' with the 'iCols' from the second dataset.

 library(data.table)#v1.9.6+
Cols <- names(df1)[-1]
iCols <- paste0('i.', Cols)
setDT(df1)[df2, (Cols) := mget(iCols), on= 'ID'][]
# ID Measurement1 Measurement2
#1: 1 45 104
#2: 2 10 11
#3: 3 23 99
#4: 4 21 22

data

df1 <- structure(list(ID = 1:4, Measurement1 = c(45L, 34L, 23L, 56L), 
Measurement2 = c(104L, 87L, 99L, 67L)), .Names = c("ID",
"Measurement1", "Measurement2"), class = "data.frame",
row.names = c(NA, -4L))

df2 <- structure(list(ID = c(2L, 4L), Measurement1 = c(10L, 21L),
Measurement2 = c(11L,
22L)), .Names = c("ID", "Measurement1", "Measurement2"),
class = "data.frame", row.names = c(NA, -2L))

Update single row of data frame in R

You can try the following:

df_table[df_table$Name == input$df, 'Value'] <- new_value

This will update the Value column for all rows where the value in Name is the same as input$df which in your example is Versicolor

Update specific row and column of dataframe

I would store your data also in reactiveValues. In addition, you can move your output outside of your observeEvent. This server function should work based on your description.

server <- function(input, output) {
vals <- reactiveValues(active_row = 1, data = dataframe)
observeEvent(input$next_button,{
vals$data[vals$active_row, "colour"] = input$colour
vals$active_row = vals$active_row + 1
})
output$dataframe <- renderDataTable(vals$data)
}

R: Updating a data frame with another data frame

merge then aggregate:

aggregate(. ~ Index, data=merge(df1, df2, all=TRUE), na.omit, na.action=na.pass )

# Index B C A
#1 1 1 1 1
#2 2 2 2 2
#3 3 3 3 3
#4 4 4 5 4
#5 5 4 5 5
#6 6 4 5 6

Or in dplyr speak:

df1 %>% 
full_join(df2) %>%
group_by(Index) %>%
summarise_each(funs(na.omit))

#Joining by: c("Index", "B", "C")
#Source: local data frame [6 x 4]
#
# Index A B C
# (dbl) (int) (dbl) (dbl)
#1 1 1 1 1
#2 2 2 2 2
#3 3 3 3 3
#4 4 4 4 5
#5 5 5 4 5
#6 6 6 4 5

Updating rows of dataframe with other dataframe column vlaue for each group in R

Here's one approach. First, I make a version of df2 with the dates stored as dates, which'll make it simpler to use them for calculations, and call that date_limits. (It's not strictly necessary here since your date strings' alphabetical sorting will also be chronological, but I think it's good practice.) I don't need the x/y values since they're in df1 already.

library(tidyverse); library(lubridate)
date_limits <- df2 %>%
mutate(max_date = ymd(date)) %>%
select(max_date, location, location_id)

Then we can join those dates onto df1 using dplyr::left_join, sort of like vlookup in excel, or merge in base R. It will by default use all the common variables (in this case location and location_id) to bring in the max_date for that location.

Then I change y and x using mutate(across(... so that if the max_date we pulled in is later than the date, change it to NA, otherwise leave it as is.

df1 %>% 
mutate(date = ymd(date)) %>%
left_join(date_limits) %>%
mutate(across(y:x, ~if_else(date > max_date, NA_integer_, .)))

Result

Joining, by = c("location", "location_id")
date location location_id y x max_date
1 2022-02-02 A 1 NA NA 2022-02-01
2 2022-02-02 B 2 45 67 2022-02-02
3 2022-02-02 C 3 NA NA 2022-01-30
4 2022-02-02 D 4 NA NA 2022-01-31
5 2022-02-01 A 1 37 67 2022-02-01
6 2022-02-01 B 2 82 23 2022-02-02
7 2022-02-01 C 3 NA NA 2022-01-30
8 2022-02-01 D 4 NA NA 2022-01-31
9 2022-01-31 A 1 61 37 2022-02-01
10 2022-01-31 B 2 90 65 2022-02-02
11 2022-01-31 C 3 NA NA 2022-01-30
12 2022-01-31 D 4 12 23 2022-01-31
13 2022-01-30 A 1 38 48 2022-02-01
14 2022-01-30 B 2 57 53 2022-02-02
15 2022-01-30 C 3 75 95 2022-01-30
16 2022-01-30 D 4 76 19 2022-01-31

How can I update these rows that match a condition in another column of my data frame?

You could also use mutate function and refer to column names without dollar sign and data frame name as if they are like any objects in R:

library(dplyr)

df %>%
mutate(Role = if_else(Name == 'Sam', 'TC', Role))

# A tibble: 7 × 3
Name Role Number
<chr> <chr> <int>
1 Sam TC 1
2 Jane TC 2
3 Sam TC 3
4 Sam TC 4
5 James RX 5
6 Mary TC 6
7 Swain TC 7

Update row values based on condition in R

A super easy base solution

df <- data.frame(cue=sample(c(1:3),10,replace = T),c2=sample(c(0,1),10,replace = T),c3=sample(c(0,1),10,replace = T))

df$c2 <- ifelse(df$cue==2,1,0)
df$c3 <- ifelse(df$cue==3,1,0)

EDIT

to add another dplyr solution

df <- dplyr::mutate(df,c2= ifelse(cue==2,1,0),c3= ifelse(cue==3,1,0))

R Data.Table: Dynamically Update a Different Column for each Row

With the OP's code, replace can work

test[, (2:4) := replace(.SD, which.max(.SD), max(.SD, na.rm = TRUE) - 0.1 * ttl), 
by = 1:nrow(test),.SDcols = 2:4]

-output

> test
thing1 A B C ttl
1: AAA 8.9 2.0 6.0 1
2: BBB 5.0 6.9 2.0 1
3: CCC 4.0 2.0 4.7 3
4: DDD 2.0 5.8 4.0 2
5: EEE 4.9 3.0 1.0 1

In base R, this may be faster with row/column indexing

test1 <- as.data.frame(test)
m1 <- cbind(seq_len(nrow(test1)), max.col(test1[2:4], "first"))
test1[2:4][m1] <- test1[2:4][m1] - 0.1 * test1$ttl


Related Topics



Leave a reply



Submit