当前位置: 首页 > 知识库问答 >
问题:

根据其他列中的最小值查找列值和名称

冯敏达
2023-03-14

我有一个如下所示的数据表

library( data.table )

dt <- data.table( p1 = c("a", "b", "c", "d", "e", "f", "g"), 
                  p2 = c("b", "c", "d", "a", "f", "g", "h"), 
                  p3 = c("z", "x", NA, NA, "y", NA, "s"), 
                  t1 = c(1, 2, 3, NA, 5, 6, 7), 
                  t2 = c(7, 6, 5, NA, 3, 2, NA), 
                  t3 = c(8, 3, NA, NA, 2, NA, 1) )

#    p1 p2   p3 t1 t2 t3
# 1:  a  b    z  1  7  8
# 2:  b  c    x  2  6  3
# 3:  c  d <NA>  3  5 NA
# 4:  d  a <NA> NA NA NA
# 5:  e  f    y  5  3  2
# 6:  f  g <NA>  6  2 NA
# 7:  g  h    s  7 NA  1

它有代表名称的p列和代表值的t列。t1是对应于p1、t2到p2等的值...
在每一行上,p列的值都是唯一的(或NA)。t列中的值也是如此。

我要做的是创建三个新列:

  • t_min,每行所有t列的最小值(不包括NA)
  • p_min,如果t_min存在(不是NA),则p列的对应值…因此,如果t2列具有t-min值,则列p2的对应值
  • p_col_min,具有p_min值的列的名称。因此,如果p_min值来自columnp2,则“p2”

我更喜欢数据。表,因为我的实际数据包含更多的行和列。我知道熔化是一种选择,但我希望用这些数据保留我的内存,所以使用的内存越少越好(生产数据包含数百万行

到目前为止,我已经找到了一种使用以下代码创建< code>t_min列的方法:

t_cols = dt[ , .SD, .SDcols = grep( "t[1-3]", names( dt ), value = TRUE ) ]
dt[ !all( is.na( t_cols ) ), 
    t_min := do.call( pmin, c( .SD, list( na.rm = TRUE ) ) ), 
    .SDcols = names( t_cols ) ]

但是我无法全神贯注地创建p_minp_col_min列。我想which.min()会在某个地方发挥作用,但我无法弄清楚。可能是我忽略的一些简单的东西(它似乎总是...;-))。

期望输出

dt.desired <- data.table( p1 = c("a", "b", "c", "d", "e", "f", "g"), 
                          p2 = c("b", "c", "d", "a", "f", "g", "h"), 
                          p3 = c("z", "x", NA, NA, "y", NA, "s"), 
                          t1 = c(1, 2, 3, NA, 5, 6, 7), 
                          t2 = c(7, 6, 5, NA, 3, 2, NA), 
                          t3 = c(8, 3, NA, NA, 2, NA, 1),
                          t_min = c(1,2,3,NA,2,2,1),
                          p_min = c("a","b","c",NA,"y","g","s"),
                          p_col_min = c("p1","p1","p1",NA,"p3","p2","p3") )

#    p1 p2   p3 t1 t2 t3 t_min p_min p_col_min
# 1:  a  b    z  1  7  8     1     a        p1
# 2:  b  c    x  2  6  3     2     b        p1
# 3:  c  d <NA>  3  5 NA     3     c        p1
# 4:  d  a <NA> NA NA NA    NA  <NA>      <NA>
# 5:  e  f    y  5  3  2     2     y        p3
# 6:  f  g <NA>  6  2 NA     2     g        p2
# 7:  g  h    s  7 NA  1     1     s        p3

共有3个答案

万乐逸
2023-03-14

这是另一条路线:

dt[, t_min := do.call(pmin, c(.SD, na.rm = TRUE)), .SDcols = patterns('t[[:digit:]]')]

dt[!is.na(t_min),
   c('p_min', 'p_min_col') := {

     arr_ind = .SD[, which(t_min == .SD, arr.ind = TRUE), .SDcols = patterns('t[[:digit:]]')]
     arr_ind = arr_ind[order(arr_ind[, 1]), ]

     p_m = .SD[, as.matrix(.SD)[arr_ind], .SDcols = patterns('p')]
     p_m_c = grep('^p', names(.SD), value = TRUE)[arr_ind[, 2]]

     list(p_m, p_m_c)
     } 
   ]
江宏放
2023-03-14

一种简单有效的方法是循环通过“t*”列,并在一次通过中跟踪所有相应的值。

首先初始化适当的向量:

p.columns = which(startsWith(names(dt), "p"))
t.columns = which(startsWith(names(dt), "t"))

p_col_min = integer(nrow(dt))
p_min = character(nrow(dt))
t_min = rep_len(Inf, nrow(dt))

并在更新时迭代:

for(i in seq_along(p.columns)) {
    cur.min = which(dt[[t.columns[i]]] < t_min)

    p_col_min[cur.min] = p.columns[i]

    t_min[cur.min] = dt[[t.columns[i]]][cur.min]
    p_min[cur.min] = dt[[p.columns[i]]][cur.min]
}

最后,在需要的地方填写NAs:

whichNA = is.infinite(t_min)
is.na(t_min) = is.na(p_min) = is.na(p_col_min) = whichNA

t_min
#[1]  1  2  3 NA  2  2  1
p_min
#[1] "a" "b" "c" NA  "y" "g" "s"
p_col_min
#[1]  1  1  1 NA  3  2  3
颜昕
2023-03-14

我不能保证这种解决方案对于您的工作数据是否足够高效,但这是我会首先尝试的:

m1 <- as.matrix(dt[, grep('^t', names(dt)), with = FALSE])
m2 <- as.matrix(dt[, grep('^p', names(dt)), with = FALSE])

t_min <- apply(m1, 1, min, na.rm = TRUE)
t_min[is.infinite(t_min)] <- NA_real_
p_min_index <- rep(NA_integer_, length(t_min))
p_min_index[!is.na(t_min)] <- apply(m1[!is.na(t_min), ], 1, which.min)

dt[, t_min  := t_min]
dt[, p_min := m2[cbind(seq_len(nrow(m2)), p_min_index)] ]
dt[, p_min_col := grep('^p', names(dt), value = TRUE)[p_min_index] ]


#    p1 p2   p3 t1 t2 t3 t_min p_min p_min_col
# 1:  a  b    z  1  7  8     1     a        p1
# 2:  b  c    x  2  6  3     2     b        p1
# 3:  c  d <NA>  3  5 NA     3     c        p1
# 4:  d  a <NA> NA NA NA    NA  <NA>      <NA>
# 5:  e  f    y  5  3  2     2     y        p3
# 6:  f  g <NA>  6  2 NA     2     g        p2
# 7:  g  h    s  7 NA  1     1     s        p3

此外,看起来所需输出中的第二行不正确?

 类似资料:
  • 我试图找到矩阵中每列的最小值和最大值,但我当前的代码运行不正确。我试图把最小值放在一个新矩阵的第一行,最大值放在下一行,并对每一列这样做。任何帮助都将不胜感激,谢谢!

  • 第一次问问题(温柔点),因为我还没有找到任何有用的东西。 在R中,我有两个数据帧。一个(DataFrameA)有一列带有唯一日期列表。另一个(DataFrameB)也有日期列表。但是DataFrameB中的某些日期在DataFrameA中可能不存在。在这种情况下,我想将DataFrameB中的日期更新为DataFrameA中的最小日期,该日期大于DataFrameB中的日期。 在SQL中,我可能会

  • 本文向大家介绍根据MySQL中其他两个列的值来匹配列的值,包括了根据MySQL中其他两个列的值来匹配列的值的使用技巧和注意事项,需要的朋友参考一下 让我们首先创建一个表- 使用插入命令在表中插入一些记录- 使用select语句显示表中的所有记录- 这将产生以下输出- 以下是根据ID和MatchID显示FirstName的查询- 这将产生以下输出-

  • 我有一个2010年和2019年的土地覆盖类型的数据框架。Pland代表总的土地覆盖价值,1等于该特定区域相对于ID的100%。这些计算是事先进行的,id代表每个几何形状。 我想执行一个函数,该函数生成另一个具有以下描述性名称的列,其中表示要替换的名称: 可复制代码:

  • 我有一个带有几列的。其中一列包含使用货币的符号,例如欧元或美元符号。另一列包含预算值。例如,在一行中,它可能意味着5000欧元的预算,而在下一行中,它可能意味着2000美元的预算。 在熊猫我想添加一个额外的列到我的DataFrame,正常化的欧元预算。所以基本上,对于每一行,如果货币列中的符号是欧元符号,新列中的值应该是预算列中的值*1,新列中的值应该是预算列的值*0.78125如果货币栏中的符号