我的情况是我的数据框包含图像分析的结果,其中列是图像中存在的特定类的比例,因此示例数据框class_df
将如下所示:
id A B C D E F
1 0.20 0.30 0.10 0.15 0.25 0.00
2 0.05 0.10 0.05 0.30 0.10 0.40
3 0.10 0.10 0.10 0.20 0.20 0.30
这些类中的每一个都属于一个功能组,我想创建新的列,其中每个功能组的比例是从类中计算出来的。映射class_fg
class fg
A Z
B Z
C Z
D Y
E Y
F X
并且所需的结果是(添加行以显示所需的新列):
id A B C D E F | X Y Z
1 0.20 0.30 0.10 0.15 0.25 0.00 | 0.00 0.40 0.60
2 0.05 0.10 0.05 0.30 0.10 0.40 | 0.40 0.40 0.20
3 0.10 0.10 0.10 0.20 0.20 0.30 | 0.30 0.40 0.30
我可以使用
一次完成一个功能组first_fg <- class_fg %>%
filter(fg == "Z") %>%
select(class) %>%
unlist()
class_df <- class_df %>%
mutate(Z = rowSums(select(., one_of(first_fg))))
当然有更好的方法可以计算每个功能组的行总和,而不必为每个组重复此代码?也许使用purrr?
答案 0 :(得分:7)
我们可以split
&#39; class_df&#39;通过&#39; class&#39;,使用list
循环map
元素,select
&#39; class_df&#39;并获得rowSums
library(tidyverse)
class_fg %>%
split(.$fg) %>%
map_df(~ class_df %>%
select(one_of(.x$class)) %>%
rowSums) %>%
bind_cols(class_df, .)
# id A B C D E F X Y Z
#1 1 0.20 0.3 0.10 0.15 0.25 0.0 0.0 0.4 0.6
#2 2 0.05 0.1 0.05 0.30 0.10 0.4 0.4 0.4 0.2
#3 3 0.10 0.1 0.10 0.20 0.20 0.3 0.3 0.4 0.3
或按nest
进行分组,然后rowSums
按map
ping list
元素
class_fg %>%
group_by(fg) %>%
nest %>%
mutate(out = map(data, ~ class_df %>%
select(one_of(.x$class)) %>%
rowSums)) %>%
select(-data) %>%
unnest %>%
unstack(., out ~ fg) %>%
bind_cols(class_df, .)
答案 1 :(得分:6)
始终以长格式处理数据更容易。因此,使用class_df
将tidyr:gather
更改为长格式,然后加入class_fg
。以长格式对数据执行分析。最后,以宽格式传播以匹配预期结果。
library(tidyverse)
class_df %>% gather(key, value, -id) %>%
inner_join(class_fg, by=c("key" = "class")) %>%
group_by(id, fg) %>%
summarise(value = sum(value)) %>%
spread(fg, value) %>%
inner_join(class_df, by="id") %>% as.data.frame()
# id X Y Z A B C D E F
# 1 1 0.0 0.4 0.6 0.20 0.3 0.10 0.15 0.25 0.0
# 2 2 0.4 0.4 0.2 0.05 0.1 0.05 0.30 0.10 0.4
# 3 3 0.3 0.4 0.3 0.10 0.1 0.10 0.20 0.20 0.3
数据:强>
class_fg <- read.table(text =
"class fg
A Z
B Z
C Z
D Y
E Y
F X",
header = TRUE, stringsAsFactors = FALSE)
class_df <- read.table(text =
"id A B C D E F
1 0.20 0.30 0.10 0.15 0.25 0.00
2 0.05 0.10 0.05 0.30 0.10 0.40
3 0.10 0.10 0.10 0.20 0.20 0.30",
header = TRUE, stringsAsFactors = FALSE)
答案 2 :(得分:5)
又一种选择,以及已经提供的工作解决方案,
将使用https://github.com/coobird/thumbnailator
使用library(tidyverse)
包来构建表达式来计算每个表达式中的总和
基。
psum <- function(...) reduce(list(...), `+`)
首先,定义一个辅助函数,用于执行向量的元素和:
class_fg
将分组从sum_exprs <- with(class_fg, split(class, fg)) %>%
map(~ rlang::expr(psum(!!!rlang::syms(.x))))
sum_exprs
#> $X
#> psum(F)
#>
#> $Y
#> psum(D, E)
#>
#> $Z
#> psum(A, B, C)
提取到列表中然后我们可以构建
用于计算每组总和的表达式列表:
mutate
准备好表达式列表后,我们可以quasiquotation将它们class_df %>%
mutate(!!!sum_exprs)
#> id A B C D E F X Y Z
#> 1 1 0.20 0.3 0.10 0.15 0.25 0.0 0.0 0.4 0.6
#> 2 2 0.05 0.1 0.05 0.30 0.10 0.4 0.4 0.4 0.2
#> 3 3 0.10 0.1 0.10 0.20 0.20 0.3 0.3 0.4 0.3
加入到#disable multi-touch emulation
from kivy.config import Config
Config.set('input', 'mouse', 'mouse,multitouch_on_demand')
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.image import Image
#--------------------------------------------------------------------
Builder.load_string("""
<RootWidget>:
BoxLayout:
orientation: 'vertical'
padding: "10dp"
BoxLayout:
size_hint_y: 3
Widget: # to fill the line from left
Button:
text: "Button"
font_size: 40
text_size: self.size
halign: 'center'
valign: 'bottom'
padding_y: 10
#Adding Image you can comment this part
Image:
source: 'img/calender1.png'
center_x: self.parent.center_x
center_y: self.parent.center_y +10
Widget:# to fill the line from right
BoxLayout:
size_hint_y: 10
""")
#-----------------------------------------------------------------------
class RootWidget(BoxLayout):
pass
#-----------------------------------------------------------------------
class MyApp(App):
def build(self):
return RootWidget()
if __name__ == '__main__':
MyApp().run()
的数据中:
Button:
text: "Button"
font_size: 40
text_size: self.size
halign: 'center'
valign: 'bottom'
padding_y: 10
(我在他的答案中使用了@MKR提供的代码来创建数据)。
由"bang-bang-bang" (!!!
)(v0.2.0)创建于2018-05-22。
答案 3 :(得分:1)
我通常的方法是坚持base
R,只要数据集不会太大。在您的情况下,base
R解决方案将是:
class_df=as.data.frame(
c(class_df,
lapply(split(class_fg,class_fg$fg),
function(x) rowSums(class_df[,x$class,drop=FALSE]))))
class_df
# id A B C D E F X Y Z
#1 1 0.20 0.3 0.10 0.15 0.25 0.0 0.0 0.4 0.6
#2 2 0.05 0.1 0.05 0.30 0.10 0.4 0.4 0.4 0.2
#3 3 0.10 0.1 0.10 0.20 0.20 0.3 0.3 0.4 0.3
如果数据集太大,我使用data.table
。解决问题的data.table
解决方案:
library(data.table)
class_dt=data.table(class_df)
grps=split(class_fg,class_fg$fg)
for (g in grps) class_dt[,c(g$fg[1]):=rowSums(.SD),.SDcols=g$class,]
class_dt
# id A B C D E F X Y Z
#1: 1 0.20 0.3 0.10 0.15 0.25 0.0 0.0 0.4 0.6
#2: 2 0.05 0.1 0.05 0.30 0.10 0.4 0.4 0.4 0.2
#3: 3 0.10 0.1 0.10 0.20 0.20 0.3 0.3 0.4 0.3
答案 4 :(得分:0)
在列子集上使用tidyverse
的另一个rowSums
解决方案:
library(tidyverse)
class_fg %>%
group_by(fg) %>%
summarize(list(rowSums(class_df[class]))) %>%
spread(1,2) %>%
unnest() %>%
bind_cols(class_df, .)
#> id A B C D E F X Y Z
#> 1 1 0.20 0.3 0.10 0.15 0.25 0.0 0.0 0.4 0.6
#> 2 2 0.05 0.1 0.05 0.30 0.10 0.4 0.4 0.4 0.2
#> 3 3 0.10 0.1 0.10 0.20 0.20 0.3 0.3 0.4 0.3
或者为了荣耀代码高尔夫:
x <- with(class_fg, tapply(class, fg, reformulate))
mutate(class_df, !!!map(x, ~as.list(.)[[2]]))
#> id A B C D E F X Y Z
#> 1 1 0.20 0.3 0.10 0.15 0.25 0.0 0.0 0.4 0.6
#> 2 2 0.05 0.1 0.05 0.30 0.10 0.4 0.4 0.4 0.2
#> 3 3 0.10 0.1 0.10 0.20 0.20 0.3 0.3 0.4 0.3