Pandas: 从Series创建DataFrame

70

以下是我的当前代码 - 我正在导入一个MAT文件并尝试从其中的变量创建一个DataFrame:

mat = loadmat(file_path)  # load mat-file
Variables = mat.keys()    # identify variable names

df = pd.DataFrame         # Initialise DataFrame

for name in Variables:

    B = mat[name]
    s = pd.Series (B[:,1])

所以在循环内,我可以创建每个变量的一系列值(它们是带有两列的数组 - 所以我需要的值在第二列)

我的问题是如何将这些系列值附加到数据框中?我已经查看了文档,但是没有一个示例符合我尝试做的事情。

4个回答

83

这里是创建 DataFrame 的方法,其中每个序列是一行

对于单个序列(导致单行 DataFrame):

series = pd.Series([1,2], index=['a','b'])
df = pd.DataFrame([series])

对于具有相同索引的多个系列:

cols = ['a','b']
list_of_series = [pd.Series([1,2],index=cols), pd.Series([3,4],index=cols)]
df = pd.DataFrame(list_of_series, columns=cols)

对于可能具有不同索引的多个系列:

list_of_series = [pd.Series([1,2],index=['a','b']), pd.Series([3,4],index=['a','c'])]
df = pd.concat(list_of_series, axis=1).transpose()

要创建一个 每个序列是一列 的 DataFrame,请参见其他答案。或者,可以创建一个 每个序列是一行 的 DataFrame,如上所述,然后使用 df.transpose()。但是,如果列具有不同的数据类型,则后一种方法效率低。


45

无需初始化一个空的DataFrame(甚至不需要这样做,您需要使用带有括号的pd.DataFrame())。

相反,要创建一个每个序列都是列的DataFrame:

  1. 创建一个Series列表series
  2. 使用df = pd.concat(series, axis=1)在水平方向上连接它们。

例如:

series = [pd.Series(mat[name][:, 1]) for name in Variables]
df = pd.concat(series, axis=1)

1
汤姆,这很好用 - 唯一的问题是生成的数据框中的列是按数字命名的。我该如何在生成的数据框中使用“name”作为列名? - BMichell
5
抱歉,我自己回答了这个问题... df.columns = 变量 - BMichell

13

现在有一个pandas.Series.to_frame方法:

Series.to_frame(name=NoDefault.no_default)

Convert Series to DataFrame.

Parameters

nameobject, optional: The passed name should substitute for the series name (if it has one).

Returns

DataFrame: DataFrame representation of Series.

Examples

s = pd.Series(["a", "b", "c"], name="vals")
s.to_frame()

2
我��另一种可能更快的方法是: 1)使用字典推导式获取所需的字典(即,每个数组的第二列) 2)然后使用pd.DataFrame直接从字典创建实例,而不必循环每个列并连接。
假设您的mat看起来像这样(如果您的mat已从文件加载,则可以忽略此内容):
In [135]: mat = {'a': np.random.randint(5, size=(4,2)),
   .....: 'b': np.random.randint(5, size=(4,2))}

In [136]: mat
Out[136]: 
{'a': array([[2, 0],
        [3, 4],
        [0, 1],
        [4, 2]]), 'b': array([[1, 0],
        [1, 1],
        [1, 0],
        [2, 1]])}

那么您可以这样做:

In [137]: df = pd.DataFrame ({name:mat[name][:,1] for name in mat})

In [138]: df
Out[138]: 
   a  b
0  0  0
1  4  1
2  1  0
3  2  1

[4 rows x 2 columns]

这是一个不错的解决方案,谢谢!在字典(或列表)推导中是否可以添加if语句来忽略大小不同的数组?我从我的MAT文件中得到的字典有几百个2x4000的数组和一些不同大小的随机数组。 - BMichell
你可以在 for 循环后添加 if 语句,例如 {name:mat[name][:,1] for name in mat if ... } - Happy001
使用字典推导式的缺点是标准 Python 字典中的键是无序的,因此列的顺序不会被保留。 - Jaan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接