#r #difference
#r #разница
Вопрос:
У меня есть 2 набора данных, я хочу для каждой строки в datset1 вычислить разницу между всеми строками в другом наборе данных2. Я также заменяю любую отрицательную разницу на 0. Вот простой пример моих 2 наборов данных (потому что у меня есть наборы данных около 1000 * 1000).
df1 <- data.frame(ID = c(1, 2), Obs = c(1.0, 2.0), var=c(2.0,5.0))
df2 <- data.frame(ID = c(2, 1), Obs = c(3.0, 2.0),var=c(7.0,3.0))
df1
ID Obs var
1 1 1 2
2 2 2 5
df2
ID Obs var
1 2 3 7
2 1 2 3
for(i in 1:nrow(df1)){
b1=as.matrix(df1)
b2=as.matrix(df2)
diff= b1-b2
diff[which(diff < 0 )] <- 0
diff.data= data.frame(cbind(diff, total = rowSums(diff)))
}
diff.data
ID Obs var total
1 0 0 0 0
2 1 0 2 3
Это то, что я смог сделать, я сделал разницу между 2 наборами данных, заменил отрицательные значения на 0, а также был заинтересован в суммировании значений столбцов после. Для первой строки в df1 я хотел бы вычислить разницу между всеми строками в df2, а для второй строки в df1 вычислить разницу между всеми строками в df2 (и так далее). Обратите внимание, что я не должен вычислять разницу между идентификаторами (я не знаю, как это сделать, может быть, изменить diff= b1-b2
на diff= b1[,-1]-b2[,-1]
? ). Я хочу сохранить идентификатор из df1, чтобы отслеживать моих пациентов (случай моего набора данных). Я хотел бы иметь что-то подобное
diff.data
ID Obs var total
1 0 0 0
1 0 0 0
2 0 0 0
2 0 2 2
Заранее благодарю вас за помощь.
Вот что у меня есть, используя ваш ответ, я хотел создать простую функцию. Но я хотел бы иметь возможность, чтобы мои наборы данных могли быть либо матрицами, либо фреймами данных, я смог сгенерировать ошибку, только если наборы данных не являются фреймами данных:
difference=function(df1,df2){
if(class(df1) != "data.frame" || class(df2) != "data.frame") stop(" df1 or df2 is not a dataframe!")
df1=data.frame(df1)
df2=data.frame(df2)
ID1=seq(nrow(df1))
ID2=seq(nrow(df2))
new_df1 = df1[rep(ID1, each = nrow(df2)), ]
new_df1[-1] = new_df1[-1] - df2[rep(seq(nrow(df2)), nrow(df1)), -1]
new_df1[new_df1 < 0] = 0
new_df1$total = rowSums(new_df1[-1])
rownames(new_df1) = NULL
output=new_df1
return(output)
}
Я знаю тот факт, что я указал df1=data.frame(df1) должен быть фреймом данных, просто я не знаю, как также включить, что это может быть матрица.
Еще раз заранее благодарю вас за помощь.
Ответ №1:
Вы можете повторять каждую строку в df1
with for nrow(df2)
times и каждую строку в df2
for nrow(df1)
times, чтобы размер фреймов данных был одинаковым, и мы могли напрямую вычитать значения.
#Repeat each row of df1 nrow(df2) times
new_df1 <- df1[rep(df1$ID, each = nrow(df2)), ]
#Repeat rows of df2 and subtract
new_df1[-1] <- new_df1[-1] - df2[rep(seq(nrow(df2)), nrow(df1)), -1]
#Replace negative values with 0
new_df1[new_df1 < 0] <- 0
#Add row-wise sum
new_df1$total <- rowSums(new_df1[-1])
#Remove rownames
rownames(new_df1) <- NULL
new_df1
# ID Obs var total
#1 1 0 0 0
#2 1 0 0 0
#3 2 0 0 0
#4 2 0 2 2
Комментарии:
1. Спасибо @Ronak Shah за помощь! Я действительно одобряю это! Не могли бы вы, пожалуйста, взглянуть на мой код и сказать мне, что мне делать, если я хочу, чтобы мои наборы данных были либо матричными, либо фреймами данных? На самом деле я не знаю, должен ли я ответить на свой вопрос, чтобы опубликовать измененный код, или просто отредактировать свой вопрос? все еще новичок в Stack. Спасибо!
2. Вы можете отредактировать свой вопрос, включив в него имеющийся у вас код.
3. Спасибо @Ronak! Я отредактировал свой пост, я был бы признателен за вашу помощь.
4. Почему бы не использовать
is.data.frame
иis.matrix
не узнать, являются ли передаваемые данные фреймом данных или матрицей. Что-то вроде этогоif(!(is.data.frame(df1) amp;amp; is.data.frame(df2) || is.matrix(df1) amp;amp; is.matrix(df2))) stop('')
5. Спасибо @Ronak! Это работает. Сначала я подумал, почему бы просто не использовать
if(class(df1) = "character" || class(df2) = "character" )
thenstop
, но я боялся, что пользователь введет что-нибудь еще и продолжит вычисления. Таким образом, я уверен. Еще раз спасибо за вашу помощь и терпение !