Learning R 5 - Lists and Data Frames

https://github.com/cccxm/deep-learning/tree/master/R/learning-r/c-5

章节目标

  • 能够创建list和data.frame

  • 能够使用length,names以及一些其他的检查和操作这些变量的函数

  • 理解什么是NULL以及如何使用它

  • 理解递归变量和原子变量的不同

  • 了解关于list和data.frame的基本操作

Lists

List可以理解为其中元素类型可以不同的向量。

创建链表

使用list函数可以创建一个链表。

> my_list <- list(c(1,2,3),matrix(c(1,2,3,4),nrow = 2))
> my_list
[[1]]
[1] 1 2 3

[[2]]
     [,1] [,2]
[1,]    1    3
[2,]    2    4

和向量不同的是,链表中不会合并数据。

使用names函数可以给链表中的元素命名。

> names(my_list) <- c('vector','matrix')
> my_list
$vector
[1] 1 2 3

$matrix
     [,1] [,2]
[1,]    1    3
[2,]    2    4

除了使用names函数外,也可以在链表创建时指定名称

> my_list <- list(
+   vector=c(1,2,3),
+   matrix=matrix(1:4,nrow = 2)
+ )
> my_list
$vector
[1] 1 2 3

$matrix
     [,1] [,2]
[1,]    1    3
[2,]    2    4

原子变量和递归变量

由于链表的特性,链表中的元素仍然可以是一个链表,所以链表可以被认为是一个可递归的变量。

使用is.atomicis.recursive函数可以判断变量的类型

> is.atomic(list())
[1] FALSE
> is.atomic(numeric())
[1] TRUE

链表的长度与运算

链表的长度只与它顶层元素的数量有关。

> length(my_list)
[1] 2

链表不能像矩阵那样测量维度,行数,列数等信息,但是提供了一个类似名称的函数。

> nrow(my_list)
NULL
> NROW(my_list)
[1] 2
> NCOL(my_list)
[1] 1

木的灵魂的两个函数。

关于运算:链表不能像向量一样直接在其对象上运算。

> 1:4 + 2:5
[1] 3 5 7 9
> list(c(1:4))+list(c(2:5))

# Error in list(c(1:4)) + list(c(2:5)): 二进列运算符中有非数值参数

直接在链表上的运算会提示错误。

需要将待运算的数据转换成向量之后才能正常运算结果。例如

> list(c(1:4))[[1]]+list(c(2:5))[[1]]
[1] 3 5 7 9

链表的索引操作

假设链表结构如下

> my_list <- list(
+   first = 1,
+   second = 2,
+   thrid = list(
+     alpha = 3.1,
+     beta = 3.2
+   )
+ )

与向量操作类似,可以直接使用方括号形式的索引获取元素。

> my_list[1:2]
$first
[1] 1

$second
[1] 2

> my_list[-3]
$first
[1] 1

$second
[1] 2

> my_list['first']
$first
[1] 1

> my_list[c(T,F,F)]
$first
[1] 1

**注意:**以上通过索引方式获取的对象仍然是个链表。如果我们需要获取对应的内容,则需要使用双重中括号。

> typeof(my_list[1])
[1] "list"
> typeof(my_list[[1]])
[1] "double"

除了使用typeof输出类型的名称,还可以用逻辑运算函数is.list来判断当前是否是链表类型。

除了使用方括号索引获取对象,还可以使用$加名称查找对应的元素,注意:只要表示唯一,可以使用名字的简写。

> l <- list(
+   same1 = 1:4,
+   same2 = 5:8,
+   other = 9:12
+ )
> l$other
[1]  9 10 11 12
> l$o
[1]  9 10 11 12
> l$same
NULL

$符号的作用是取值,等价于双重中括号

> typeof(l['other']) == typeof(l$other)
[1] FALSE
> typeof(l[['other']]) == typeof(l$other)
[1] TRUE

链表和向量的转换

as.*函数可以实现类型的转换。

> as.list(1:4)
[[1]]
[1] 1

[[2]]
[1] 2

[[3]]
[1] 3

[[4]]
[1] 4

> as.vector(list(1:4))
[[1]]
[1] 1 2 3 4

> as.vector(list(a=1:2,b=3:4))
$a
[1] 1 2

$b
[1] 3 4

> unlist(list(a=1:2,b=3:4))
a1 a2 b1 b2 
 1  2  3  4 

链表的拼接

c函数可以应用于链表表示拼接。使用方式如下

> com_list <- c(list(1:3), 4)
> com_list
[[1]]
[1] 1 2 3

[[2]]
[1] 4

> typeof(com_list)
[1] "list"

使用矩阵函数cbind或者rbind同样可以实现链表的拼接

> cbind(
+   list(a = 1, b = 2),
+   list(c = 3, d = 4)
+ )
  [,1] [,2]
a 1    3   
b 2    4   
> rbind(
+   list(a = 1, b = 2),
+   list(c = 3, d = 4)
+ )
     a b
[1,] 1 2
[2,] 3 4

Data Frame

数据框是一种表格结构的对象,与矩阵类似,但不要求类型相同。

创建数据框对象

使用data.frame函数就可创建一个数据框对象。

> data.frame(
+   x = 1,
+   y = 2:3,
+   z = 4:7
+ )
  x y z
1 1 2 4
2 1 3 5
3 1 2 6
4 1 3 7

基本的数据框操作

转置

> df <- data.frame(
+   x = 1,
+   y = 2:3,
+   z = 4:7
+ )
> df
  x y z
1 1 2 4
2 1 3 5
3 1 2 6
4 1 3 7
> t(df)
  [,1] [,2] [,3] [,4]
x    1    1    1    1
y    2    3    2    3
z    4    5    6    7

列合并

将一个数据框追加到另一个数据框的右侧

> df1 <- data.frame(
+   x = 1,
+   y = 2:3,
+   z = 4:7
+ )
> df2 <- data.frame(
+   a = letters[1:4],
+   b = letters[5:8]
+ )
> cbind(df1, df2)
  x y z a b
1 1 2 4 a e
2 1 3 5 b f
3 1 2 6 c g
4 1 3 7 d h

行合并

将两个数据框按照行扩展的方式追加

> df1 <- data.frame(
+   x = 1,
+   y = 2:3,
+   z = 4:7
+ )
> df2 <- data.frame(
+   x = 1:3,
+   y = 4:6,
+   z = 7:9
+ )
> rbind(df1, df2)
  x y z
1 1 2 4
2 1 3 5
3 1 2 6
4 1 3 7
5 1 4 7
6 2 5 8
7 3 6 9

有条件合并

> df1 <- data.frame(
+   names = c('apple', 'orange'),
+   price = c(6.9, 8.9)
+ )
> df2 <- data.frame(
+   names = c('apple', 'orange'),
+   color = c('red', 'orange')
+ )
> merge(df1, df2, by = 'names')
   names price  color
1  apple   6.9    red
2 orange   8.9 orange
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
To merge k sorted linked lists, one approach is to repeatedly merge two of the linked lists until all k lists have been merged into one. We can use a priority queue to keep track of the minimum element across all k linked lists at any given time. Here's the code to implement this idea: ``` struct ListNode { int val; ListNode* next; ListNode(int x) : val(x), next(NULL) {} }; // Custom comparator for the priority queue struct CompareNode { bool operator()(const ListNode* node1, const ListNode* node2) const { return node1->val > node2->val; } }; ListNode* mergeKLists(vector<ListNode*>& lists) { priority_queue<ListNode*, vector<ListNode*>, CompareNode> pq; for (ListNode* list : lists) { if (list) { pq.push(list); } } ListNode* dummy = new ListNode(-1); ListNode* curr = dummy; while (!pq.empty()) { ListNode* node = pq.top(); pq.pop(); curr->next = node; curr = curr->next; if (node->next) { pq.push(node->next); } } return dummy->next; } ``` We start by initializing a priority queue with all the head nodes of the k linked lists. We use a custom comparator that compares the values of two nodes and returns true if the first node's value is less than the second node's value. We then create a dummy node to serve as the head of the merged linked list, and a current node to keep track of the last node in the merged linked list. We repeatedly pop the minimum node from the priority queue and append it to the merged linked list. If the popped node has a next node, we push it onto the priority queue. Once the priority queue is empty, we return the head of the merged linked list. Note that this implementation has a time complexity of O(n log k), where n is the total number of nodes across all k linked lists, and a space complexity of O(k).
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值