Saya ingin mengurutkan data.bingkai dengan beberapa kolom. Misalnya, dengan data.frame di bawah ini saya ingin mengurutkan berdasarkan kolom z
(turun) maka pada kolom b
(ascending):
dd <- data.frame(b = factor(c("Hi", "Med", "Hi", "Low"),
levels = c("Low", "Med", "Hi"), ordered = TRUE),
x = c("A", "D", "A", "C"), y = c(8, 3, 9, 9),
z = c(1, 1, 1, 2))
dd
b x y z
1 Hi A 8 1
2 Med D 3 1
3 Hi A 9 1
4 Low C 9 2
Anda dapat menggunakan order()
fungsi langsung tanpa menggunakan add-on tools -- lihat ini jawaban sederhana yang menggunakan trik yang tepat dari atas `contoh(order) kode:
R> dd[with(dd, order(-z, b)), ]
b x y z
4 Low C 9 2
2 Med D 3 1
1 Hi A 8 1
3 Hi A 9 1
Mengedit beberapa 2+ tahun kemudian: Itu hanya bertanya bagaimana untuk melakukan hal ini dengan indeks kolom. Jawabannya adalah untuk hanya lulus pengurutan yang diinginkan kolom(s) untuk urutan ()
fungsi:
R> dd[order(-dd[,4], dd[,1]), ]
b x y z
4 Low C 9 2
2 Med D 3 1
1 Hi A 8 1
3 Hi A 9 1
R>
daripada menggunakan nama kolom (dan dengan()
untuk lebih mudah/lebih akses langsung).
order
dari base
mengatur
dari dplyr
setorder
dan setorderv
dari data.meja
mengatur
dari plyr
semacam
dari taRifx
orderBy
dari doBy
sortData
dari Deducer
Sebagian besar waktu anda harus menggunakan dplyr
atau data.tabel
solusi, kecuali setelah tidak ada dependensi adalah penting, dalam hal ini menggunakan dasar::order
.
Saya baru-baru ini ditambahkan semacam.data.bingkai untuk CRAN paket, sehingga kelas yang kompatibel seperti yang dibahas di sini: https://stackoverflow.com/questions/6836963/best-way-to-create-generic-method-consistency-for-sort-data-frame
Oleh karena itu, mengingat data.bingkai dd, anda bisa urutkan sebagai berikut:
dd <- data.frame(b = factor(c("Hi", "Med", "Hi", "Low"),
levels = c("Low", "Med", "Hi"), ordered = TRUE),
x = c("A", "D", "A", "C"), y = c(8, 3, 9, 9),
z = c(1, 1, 1, 2))
library(taRifx)
sort(dd, f= ~ -z + b )
Jika anda adalah salah satu dari penulis asli dari fungsi ini, silahkan hubungi saya. Diskusi publik domaininess di sini: http://chat.stackoverflow.com/transcript/message/1094290#1094290
Anda juga dapat menggunakan mengatur()
fungsi dari plyr
sebagai Hadley kemukakan di thread di atas:
library(plyr)
arrange(dd,desc(z),b)
Tolok ukur: Perhatikan bahwa saya dimuat masing-masing paket di new R sesi karena ada banyak konflik. Secara khusus memuat doBy paket penyebab sort
untuk kembali "objek berikut(s) yang bertopeng dari 'x (posisi 17)': b, x, y, z", dan loading Deducer paket menimpa semacam.data.frame
dari Kevin Wright atau taRifx paket.
#Load each time
dd <- data.frame(b = factor(c("Hi", "Med", "Hi", "Low"),
levels = c("Low", "Med", "Hi"), ordered = TRUE),
x = c("A", "D", "A", "C"), y = c(8, 3, 9, 9),
z = c(1, 1, 1, 2))
library(microbenchmark)
# Reload R between benchmarks
microbenchmark(dd[with(dd, order(-z, b)), ] ,
dd[order(-dd$z, dd$b),],
times=1000
)
Rata-rata waktu:
dd[dengan(dd, rangka(-z, b)), ]
778
dd[order(-dd$z, dd$b),]
788
library(taRifx)
microbenchmark(sort(dd, f= ~-z+b ),times=1000)
Rata-rata waktu: 1,567
library(plyr)
microbenchmark(arrange(dd,desc(z),b),times=1000)
Rata-rata waktu: 862
library(doBy)
microbenchmark(orderBy(~-z+b, data=dd),times=1000)
Rata-rata waktu: 1,694
Perhatikan bahwa doBy membutuhkan sedikit waktu untuk memuat paket.
library(Deducer)
microbenchmark(sortData(dd,c("z","b"),increasing= c(FALSE,TRUE)),times=1000)
Tidak't membuat Deducer beban. Kebutuhan JGR konsol.
esort <- function(x, sortvar, ...) {
attach(x)
x <- x[with(x,order(sortvar,...)),]
return(x)
detach(x)
}
microbenchmark(esort(dd, -z, b),times=1000)
Doesn't muncul untuk menjadi kompatibel dengan microbenchmark karena attach/detach.
m <- microbenchmark(
arrange(dd,desc(z),b),
sort(dd, f= ~-z+b ),
dd[with(dd, order(-z, b)), ] ,
dd[order(-dd$z, dd$b),],
times=1000
)
uq <- function(x) { fivenum(x)[4]}
lq <- function(x) { fivenum(x)[2]}
y_min <- 0 # min(by(m$time,m$expr,lq))
y_max <- max(by(m$time,m$expr,uq)) * 1.05
p <- ggplot(m,aes(x=expr,y=time)) + coord_cartesian(ylim = c( y_min , y_max ))
p + stat_summary(fun.y=median,fun.ymin = lq, fun.ymax = uq, aes(fill=expr))
(garis-garis memanjang dari bawah kuartil ke atas kuartil, titik adalah rata-rata)
Dengan hasil ini dan penimbangan kesederhanaan vs kecepatan, I'd harus memberikan mengangguk untuk mengatur
di plyr
paket. Memiliki sintaks sederhana namun hampir sebagai cepat sebagai basis R perintah dengan mereka berbelit-belit intrik. Biasanya brilian Hadley Wickham bekerja. Mengeluh hanya dengan itu adalah bahwa hal itu melanggar standar R nomenklatur mana menyortir benda-benda yang bisa disebut dengan jenis(objek)
, tapi aku mengerti mengapa Hadley apakah itu karena masalah yang dibahas dalam pertanyaan terkait di atas.
Dirk's jawaban yang lebih besar. Ia juga menyoroti perbedaan penting dalam sintaks yang digunakan untuk mengindeks data.frame dan data.tabel:
## The data.frame way
dd[with(dd, order(-z, b)), ]
## The data.table way: (7 fewer characters, but that's not the important bit)
dd[order(-z, b)]
Perbedaan antara dua panggilan kecil, tetapi hal ini dapat memiliki konsekuensi penting. Terutama jika anda menulis kode produksi dan/atau yang berkaitan dengan kebenaran dalam penelitian anda,'s terbaik untuk menghindari pengulangan yang tidak perlu dari nama variabel. data.meja
membantu anda melakukan hal ini.
Berikut ini's contoh bagaimana pengulangan nama-nama variabel bisa mendapatkan anda ke dalam kesulitan:
Let's mengubah konteks dari Dirk's jawaban, dan mengatakan ini adalah bagian dari proyek yang lebih besar di mana ada banyak nama objek dan mereka yang panjang dan bermakna; bukan dd
it's disebut quarterlyreport
. Menjadi :
quarterlyreport[with(quarterlyreport,order(-z,b)),]
Ok, baik-baik saja. Ada yang salah dengan itu. Berikutnya bos anda meminta anda untuk memasukkan kuartal terakhir's laporan dalam laporan. Anda pergi melalui kode anda, menambahkan objek lastquarterlyreport
di berbagai tempat dan entah bagaimana caranya (bagaimana caranya?) anda berakhir dengan ini :
quarterlyreport[with(lastquarterlyreport,order(-z,b)),]
Yang isn't apa yang anda maksud tapi kau tidak't-spot itu karena anda melakukannya dengan cepat dan it's terletak pada sebuah halaman kode yang sama. Kode doesn't jatuh di atas (tidak ada peringatan dan tidak ada kesalahan) karena R berpikir itu adalah apa yang anda maksudkan. Anda'd berharap siapa pun yang membaca laporan anda bintik-bintik ini, tapi mungkin mereka don't. Jika anda bekerja dengan bahasa pemrograman yang banyak maka keadaan ini mungkin semua akrab. Itu adalah "typo" anda'll mengatakan. I'll memperbaiki "typo" anda'll mengatakan kepada atasan anda.
Di data.tabel
kita're khawatir tentang rincian kecil seperti ini. Jadi kita've melakukan sesuatu yang sederhana untuk menghindari mengetik nama variabel dua kali. Sesuatu yang sangat sederhana. aku
ini dievaluasi dalam kerangka dd
sudah, secara otomatis. Anda don't perlu dengan()
pada semua.
Bukan
dd[with(dd, order(-z, b)), ]
it's hanya
dd[order(-z, b)]
Dan bukan
quarterlyreport[with(lastquarterlyreport,order(-z,b)),]
it's hanya
quarterlyreport[order(-z,b)]
It's perbedaan yang sangat kecil, tapi itu mungkin akan menyelamatkan leher anda satu hari. Ketika menimbang jawaban yang berbeda untuk pertanyaan ini, pertimbangkan untuk menghitung pengulangan nama-nama variabel sebagai salah satu kriteria anda dalam memutuskan. Beberapa jawaban memiliki beberapa mengulangi, yang lain tidak.
Ada banyak jawaban yang sangat baik di sini, tapi dplyr memberikan hanya sintaks yang saya dapat dengan cepat dan mudah diingat (dan sekarang digunakan sangat sering):
library(dplyr)
# sort mtcars by mpg, ascending... use desc(mpg) for descending
arrange(mtcars, mpg)
# sort mtcars first by mpg, then by cyl, then by wt)
arrange(mtcars , mpg, cyl, wt)
Untuk OP's masalah:
arrange(dd, desc(z), b)
b x y z
1 Low C 9 2
2 Med D 3 1
3 Hi A 8 1
4 Hi A 9 1
R paket data.tabelmenyediakan baik *cepat* dan *memori yang efisien* pemesanan *data.tabel* dengan lugas sintaks (bagian yang Matt telah disorot cukup baik [dalam jawabannya](https://stackoverflow.com/a/10758086/559784)). Di sana telah cukup banyak perbaikan dan juga fungsi baru
setorder()sejak saat itu. Dari
v1.9.5+,
setorder()` juga bekerja dengan data.frame.
Pertama, kita'll membuat dataset yang cukup besar dan acuan metode yang berbeda yang disebutkan dari jawaban yang lain dan kemudian daftar fitur data.tabel.
require(plyr)
require(doBy)
require(data.table)
require(dplyr)
require(taRifx)
set.seed(45L)
dat = data.frame(b = as.factor(sample(c("Hi", "Med", "Low"), 1e8, TRUE)),
x = sample(c("A", "D", "C"), 1e8, TRUE),
y = sample(100, 1e8, TRUE),
z = sample(5, 1e8, TRUE),
stringsAsFactors = FALSE)
Timing yang dilaporkan adalah dari menjalankan sistem.waktu(...)` pada fungsi-fungsi ini ditunjukkan di bawah ini. Timing ditabulasikan berikut (dalam urutan dari yang paling lambat ke cepat).
orderBy( ~ -z + b, data = dat) ## doBy
plyr::arrange(dat, desc(z), b) ## plyr
arrange(dat, desc(z), b) ## dplyr
sort(dat, f = ~ -z + b) ## taRifx
dat[with(dat, order(-z, b)), ] ## base R
# convert to data.table, by reference
setDT(dat)
dat[order(-z, b)] ## data.table, base R like syntax
setorder(dat, -z, b) ## data.table, using setorder()
## setorder() now also works with data.frames
# R-session memory usage (BEFORE) = ~2GB (size of 'dat')
# ------------------------------------------------------------
# Package function Time (s) Peak memory Memory used
# ------------------------------------------------------------
# doBy orderBy 409.7 6.7 GB 4.7 GB
# taRifx sort 400.8 6.7 GB 4.7 GB
# plyr arrange 318.8 5.6 GB 3.6 GB
# base R order 299.0 5.6 GB 3.6 GB
# dplyr arrange 62.7 4.2 GB 2.2 GB
# ------------------------------------------------------------
# data.table order 6.2 4.2 GB 2.2 GB
# data.table setorder 4.5 2.4 GB 0.4 GB
# ------------------------------------------------------------
data.tabel
's DT[order(...)]
sintaks adalah ~10x lebih cepat dari yang tercepat dari metode lain (dplyr
), sementara mengkonsumsi jumlah yang sama dari memori sebagai dplyr
.
data.tabel
's setorder()
adalah ~14x lebih cepat dari yang tercepat dari metode lain (dplyr
), saat mengambil hanya 0.4 GB memori tambahan. dat
sekarang di order, kami membutuhkan (seperti yang diperbarui oleh referensi).
Kecepatan:
data.tabel's memesan sangat cepat karena menerapkan radix memesan.
Sintaks DT[order(...)]
dioptimalkan secara internal digunakan data.tabel's cepat memesan juga. Anda dapat tetap menggunakan akrab basis R sintaks tapi mempercepat proses (dan menggunakan memori kurang).
Memori:
DF <- DF[order(...)]
Masalahnya adalah bahwa hal ini membutuhkan setidaknya dua kali (2x) memori dari objek asli. Untuk menjadi memori yang efisien, data.tabel oleh karena itu juga menyediakan fungsi setorder()
.
setorder()
menata ulang data.tabel referensi
(di tempat), tanpa membuat salinan tambahan. Hanya menggunakan memori tambahan sama dengan ukuran satu kolom.
Fitur lain:
integer
, logis
, numerik
, karakter
dan bahkan bit64::integer64
jenis.Perhatikan bahwa
faktor
,Tanggal
,POSIXct
dll.. kelas semuainteger
/numerik
jenis bawahnya dengan atribut tambahan dan karena itu didukung juga.
-
pada karakter vektor untuk mengurutkan berdasarkan kolom dalam urutan penurunan. Sebaliknya kita harus menggunakan -xtfrm(.)
. Namun, dalam data.tabel, kita hanya bisa melakukan, misalnya, dat[order(-x)]
atau setorder(dat, -x)
.
Dengan ini (sangat membantu) fungsi oleh Kevin Wright, posted in tips bagian dari R wiki, hal ini mudah dicapai.
sort(dd,by = ~ -z + b)
# b x y z
# 4 Low C 9 2
# 2 Med D 3 1
# 1 Hi A 8 1
# 3 Hi A 9 1
Misalkan anda memiliki data.frame`A
dan anda ingin mengatasinya dengan menggunakan kolom x
urutan. Sebut diurutkan data.frame
newdata
newdata <- A[order(-A$x),]
Jika anda ingin urutan menaik kemudian mengganti "-"
dengan apa-apa. Anda dapat memiliki sesuatu seperti
newdata <- A[order(-A$x, A$y, -A$z),]
dimana x
dan z
adalah beberapa kolom di data.frame
A
. Ini berarti semacam data.frame
A
dengan x
turun, y
naik z
turun.
Saya belajar tentang order
dengan contoh berikut yang kemudian saya bingung untuk waktu yang lama:
set.seed(1234)
ID = 1:10
Age = round(rnorm(10, 50, 1))
diag = c("Depression", "Bipolar")
Diagnosis = sample(diag, 10, replace=TRUE)
data = data.frame(ID, Age, Diagnosis)
databyAge = data[order(Age),]
databyAge
Satu-satunya alasan ini contoh karya adalah karena pesanan
adalah menyortir oleh vektor Usia
, bukan oleh kolom bernama Usia
di data frame data
.
Untuk melihat hal ini membuat data yang identik frame menggunakan baca.meja
dengan sedikit berbeda, nama kolom dan tanpa menggunakan apapun di atas vektor-vektor:
my.data <- read.table(text = '
id age diagnosis
1 49 Depression
2 50 Depression
3 51 Depression
4 48 Depression
5 50 Depression
6 51 Bipolar
7 49 Bipolar
8 49 Bipolar
9 49 Bipolar
10 49 Depression
', header = TRUE)
Baris di atas struktur untuk order
tidak lagi bekerja karena tidak ada vektor yang bernama usia
:
databyage = my.data[order(age),]
Berikut line bekerja karena pesanan
macam pada kolom usia
di saya.data
.
databyage = my.data[order(my.data$age),]
Saya pikir ini layak posting mengingat betapa bingung aku dengan contoh ini begitu lama. Jika posting ini tidak dianggap tepat untuk thread saya dapat menghapus itu.
EDIT: Mei 13, 2014
Di bawah ini adalah cara umum dari pengurutan data frame dengan setiap kolom tanpa menentukan nama kolom. Kode berikut menunjukkan cara untuk mengurutkan dari kiri ke kanan atau kanan ke kiri. Ini bekerja jika setiap kolom numerik. Saya belum mencoba dengan karakter kolom ditambahkan.
Saya menemukan lakukan.panggilan
kode satu atau dua bulan yang lalu di posting di berbagai situs, tetapi hanya setelah yang luas dan sulit mencari. Saya tidak yakin saya bisa pindah posting sekarang. Ini thread pertama hit untuk memesan data.bingkai
di R
. Jadi, saya pikir saya versi yang diperluas dari yang asli lakukan.panggilan
kode yang mungkin berguna.
set.seed(1234)
v1 <- c(0,0,0,0, 0,0,0,0, 1,1,1,1, 1,1,1,1)
v2 <- c(0,0,0,0, 1,1,1,1, 0,0,0,0, 1,1,1,1)
v3 <- c(0,0,1,1, 0,0,1,1, 0,0,1,1, 0,0,1,1)
v4 <- c(0,1,0,1, 0,1,0,1, 0,1,0,1, 0,1,0,1)
df.1 <- data.frame(v1, v2, v3, v4)
df.1
rdf.1 <- df.1[sample(nrow(df.1), nrow(df.1), replace = FALSE),]
rdf.1
order.rdf.1 <- rdf.1[do.call(order, as.list(rdf.1)),]
order.rdf.1
order.rdf.2 <- rdf.1[do.call(order, rev(as.list(rdf.1))),]
order.rdf.2
rdf.3 <- data.frame(rdf.1$v2, rdf.1$v4, rdf.1$v3, rdf.1$v1)
rdf.3
order.rdf.3 <- rdf.1[do.call(order, as.list(rdf.3)),]
order.rdf.3
Dalam menanggapi komentar ditambahkan dalam OP untuk cara semacam pemrograman:
Menggunakan dplyr
dan data.meja
library(dplyr)
library(data.table)
Hanya menggunakan arrange_
, yang merupakan Standar Evaluasi yang versi untuk mengatur
.
df1 <- tbl_df(iris)
#using strings or formula
arrange_(df1, c('Petal.Length', 'Petal.Width'))
arrange_(df1, ~Petal.Length, ~Petal.Width)
Source: local data frame [150 x 5]
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
(dbl) (dbl) (dbl) (dbl) (fctr)
1 4.6 3.6 1.0 0.2 setosa
2 4.3 3.0 1.1 0.1 setosa
3 5.8 4.0 1.2 0.2 setosa
4 5.0 3.2 1.2 0.2 setosa
5 4.7 3.2 1.3 0.2 setosa
6 5.4 3.9 1.3 0.4 setosa
7 5.5 3.5 1.3 0.2 setosa
8 4.4 3.0 1.3 0.2 setosa
9 5.0 3.5 1.3 0.3 setosa
10 4.5 2.3 1.3 0.3 setosa
.. ... ... ... ... ...
#Or using a variable
sortBy <- c('Petal.Length', 'Petal.Width')
arrange_(df1, .dots = sortBy)
Source: local data frame [150 x 5]
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
(dbl) (dbl) (dbl) (dbl) (fctr)
1 4.6 3.6 1.0 0.2 setosa
2 4.3 3.0 1.1 0.1 setosa
3 5.8 4.0 1.2 0.2 setosa
4 5.0 3.2 1.2 0.2 setosa
5 4.7 3.2 1.3 0.2 setosa
6 5.5 3.5 1.3 0.2 setosa
7 4.4 3.0 1.3 0.2 setosa
8 4.4 3.2 1.3 0.2 setosa
9 5.0 3.5 1.3 0.3 setosa
10 4.5 2.3 1.3 0.3 setosa
.. ... ... ... ... ...
#Doing the same operation except sorting Petal.Length in descending order
sortByDesc <- c('desc(Petal.Length)', 'Petal.Width')
arrange_(df1, .dots = sortByDesc)
info lebih lanjut di sini: https://cran.r-project.org/web/packages/dplyr/vignettes/nse.html
Hal ini lebih baik menggunakan formula seperti itu juga mencakup lingkungan untuk mengevaluasi ekspresi di
dt1 <- data.table(iris) #not really required, as you can work directly on your data.frame
sortBy <- c('Petal.Length', 'Petal.Width')
sortType <- c(-1, 1)
setorderv(dt1, sortBy, sortType)
dt1
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1: 7.7 2.6 6.9 2.3 virginica
2: 7.7 2.8 6.7 2.0 virginica
3: 7.7 3.8 6.7 2.2 virginica
4: 7.6 3.0 6.6 2.1 virginica
5: 7.9 3.8 6.4 2.0 virginica
---
146: 5.4 3.9 1.3 0.4 setosa
147: 5.8 4.0 1.2 0.2 setosa
148: 5.0 3.2 1.2 0.2 setosa
149: 4.3 3.0 1.1 0.1 setosa
150: 4.6 3.6 1.0 0.2 setosa
Demi kelengkapan: anda juga dapat menggunakan sortByCol()
fungsi dari BBmisc
paket:
library(BBmisc)
sortByCol(dd, c("z", "b"), asc = c(FALSE, TRUE))
b x y z
4 Low C 9 2
2 Med D 3 1
1 Hi A 8 1
3 Hi A 9 1
Perbandingan kinerja:
library(microbenchmark)
microbenchmark(sortByCol(dd, c("z", "b"), asc = c(FALSE, TRUE)), times = 100000)
median 202.878
library(plyr)
microbenchmark(arrange(dd,desc(z),b),times=100000)
median 148.758
microbenchmark(dd[with(dd, order(-z, b)), ], times = 100000)
median 115.872
Sama seperti kartu mekanik penyortir lama, pertama urutkan berdasarkan yang paling penting, kemudian yang berikutnya yang paling signifikan, dll. Ada perpustakaan yang diperlukan, bekerja dengan sejumlah tombol dan kombinasi dari naik dan turun tombol.
dd <- dd[order(dd$b, decreasing = FALSE),]
Sekarang kita're siap untuk melakukan yang paling penting. Semacam stabil, dan setiap hubungan yang paling penting telah diselesaikan.
dd <- dd[order(dd$z, decreasing = TRUE),]
Ini mungkin bukan yang tercepat, tetapi tentu saja sederhana dan dapat diandalkan
Hanya demi kelengkapan, sejak tidak banyak yang telah dikatakan tentang pengurutan berdasarkan kolom nomor... Itu pasti dapat dikatakan bahwa hal ini sering tidak diinginkan (karena urutan kolom yang bisa berubah, paving jalan untuk kesalahan), tetapi dalam beberapa situasi tertentu (ketika misalnya anda membutuhkan pekerjaan cepat selesai dan tidak ada risiko dari kolom mengubah pesanan), mungkin menjadi hal yang paling masuk akal untuk dilakukan, terutama ketika berhadapan dengan besar kolom.
Dalam kasus itu, apakah.call()
datang untuk menyelamatkan:
ind <- do.call(what = "order", args = iris[,c(5,1,2,3)])
iris[ind, ]
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 14 4.3 3.0 1.1 0.1 setosa
## 9 4.4 2.9 1.4 0.2 setosa
## 39 4.4 3.0 1.3 0.2 setosa
## 43 4.4 3.2 1.3 0.2 setosa
## 42 4.5 2.3 1.3 0.3 setosa
## 4 4.6 3.1 1.5 0.2 setosa
## 48 4.6 3.2 1.4 0.2 setosa
## 7 4.6 3.4 1.4 0.3 setosa
## (...)
Saya berjuang dengan solusi di atas ketika saya ingin mengotomatisasi saya proses pemesanan untuk n kolom, dan kolom nama-nama bisa berbeda setiap kali. Saya menemukan sangat membantu fungsi dari psikologi
paket untuk melakukan hal ini dengan cara yang sederhana:
dfOrder(myDf, columnIndices)
di mana columnIndices
adalah indeks dari satu atau lebih kolom, dalam urutan yang anda inginkan untuk mengurutkan mereka. Informasi lebih lanjut di sini: