如何从 Pandas 中的两列形成元组列

Posted

技术标签:

【中文标题】如何从 Pandas 中的两列形成元组列【英文标题】:How to form tuple column from two columns in Pandas 【发布时间】:2013-04-08 12:06:33 【问题描述】:

我有一个 Pandas DataFrame,我想将 'lat' 和 'long' 列组合成一个元组。

<class 'pandas.core.frame.DataFrame'>
Int64Index: 205482 entries, 0 to 209018
Data columns:
Month           205482  non-null values
Reported by     205482  non-null values
Falls within    205482  non-null values
Easting         205482  non-null values
Northing        205482  non-null values
Location        205482  non-null values
Crime type      205482  non-null values
long            205482  non-null values
lat             205482  non-null values
dtypes: float64(4), object(5)

我尝试使用的代码是:

def merge_two_cols(series): 
    return (series['lat'], series['long'])

sample['lat_long'] = sample.apply(merge_two_cols, axis=1)

但是,这会返回以下错误:

---------------------------------------------------------------------------
 AssertionError                            Traceback (most recent call last)
<ipython-input-261-e752e52a96e6> in <module>()
      2     return (series['lat'], series['long'])
      3 
----> 4 sample['lat_long'] = sample.apply(merge_two_cols, axis=1)
      5

...

AssertionError: Block shape incompatible with manager 

我该如何解决这个问题?

【问题讨论】:

【参考方案1】:
In [10]: df
Out[10]:
          A         B       lat      long
0  1.428987  0.614405  0.484370 -0.628298
1 -0.485747  0.275096  0.497116  1.047605
2  0.822527  0.340689  2.120676 -2.436831
3  0.384719 -0.042070  1.426703 -0.634355
4 -0.937442  2.520756 -1.662615 -1.377490
5 -0.154816  0.617671 -0.090484 -0.191906
6 -0.705177 -1.086138 -0.629708  1.332853
7  0.637496 -0.643773 -0.492668 -0.777344
8  1.109497 -0.610165  0.260325  2.533383
9 -1.224584  0.117668  1.304369 -0.152561

In [11]: df['lat_long'] = df[['lat', 'long']].apply(tuple, axis=1)

In [12]: df
Out[12]:
          A         B       lat      long                             lat_long
0  1.428987  0.614405  0.484370 -0.628298      (0.484370195967, -0.6282975278)
1 -0.485747  0.275096  0.497116  1.047605      (0.497115615839, 1.04760475074)
2  0.822527  0.340689  2.120676 -2.436831      (2.12067574274, -2.43683074367)
3  0.384719 -0.042070  1.426703 -0.634355      (1.42670326172, -0.63435462504)
4 -0.937442  2.520756 -1.662615 -1.377490     (-1.66261469102, -1.37749004179)
5 -0.154816  0.617671 -0.090484 -0.191906  (-0.0904840623396, -0.191905582481)
6 -0.705177 -1.086138 -0.629708  1.332853     (-0.629707821728, 1.33285348929)
7  0.637496 -0.643773 -0.492668 -0.777344   (-0.492667604075, -0.777344111021)
8  1.109497 -0.610165  0.260325  2.533383        (0.26032456699, 2.5333825651)
9 -1.224584  0.117668  1.304369 -0.152561     (1.30436900612, -0.152560909725)

【讨论】:

太棒了。谢谢你。显然需要了解 lambda 函数。 这对您的数据有效吗?如果是这样,你能分享你的熊猫版本和数据吗?我想知道为什么你的代码不起作用,它应该。 版本为0.10.1_20130131。请原谅我的无知,但是为您上传部分数据的最佳方式是什么? (仍然是一个相对新手)。 我未能在 0.10.1 上重现。最好的上传方式?您可以创建生成包含随机数据的帧的代码,它具有相同的问题并共享该代码,或者腌制上面的帧(示例)并通过免费的大文件传输服务传输它。如何腌制(两行,不带“,”):import pickle, with open('sample.pickle', 'w') as file: pickle.dump(sample, file) 我对此表示赞同,因为我需要压缩 10 列并且不想给出数据框名称 10 次。只想给列名。【参考方案2】:

熟悉zip。在处理列数据时它会派上用场。

df['new_col'] = list(zip(df.lat, df.long))

它比使用applymap 更简单、更快捷。像np.dstack 这样的东西比zip 快两倍,但不会给你元组。

【讨论】:

在python3中,你必须使用list。这应该工作:df['new_col'] = list(zip(df.lat, df.long)) @paulwasit 啊是的,我爱恨关系与 python 3 的懒惰行为。谢谢。 这种方法list(zip(df.lat, df.long)) 在 124 毫秒内比 df[['lat', 'long']].apply(tuple, axis=1) 在 14.2 秒内处理 900k 行要高效得多。比例大于100。 我正在尝试将其与更长的列列表一起使用df['new_col'] = list(zip(df[cols_to_keep])),但不断收到错误消息:Length of values does not match length of index 有什么建议吗? @PeterHansen 的回答对我有所帮助,但认为首先解压列表可能缺少* - 即df['new_col'] = list(zip(*[df[c] for c in cols_to_keep])【参考方案3】:

Pandas 有 itertuples 方法可以做到这一点:

list(df[['lat', 'long']].itertuples(index=False, name=None))

【讨论】:

【参考方案4】:

我想添加df.values.tolist()。 (只要你不介意得到一列列表而不是元组)

import pandas as pd
import numpy as np

size = int(1e+07)
df = pd.DataFrame('a': np.random.rand(size), 'b': np.random.rand(size)) 

%timeit df.values.tolist()
1.47 s ± 38.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit list(zip(df.a,df.b))
1.92 s ± 131 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

【讨论】:

当您拥有的不仅仅是这两列时:%timeit df[['a', 'b']].values.tolist()。它仍然快得多。 创建它的速度更快,但是在该列上的任何操作都将以元组形式更快。例如,尝试在一列列表和一列元组上调用 .value_counts()【参考方案5】:

你应该尝试使用pd.to_records(index=False):

import pandas as pd
df = pd.DataFrame('language': ['en', 'ar', 'es'], 'greeting': ['Hi', 'اهلا', 'Hola'])
df

   language  greeting
0       en    Hi
1       ar    اهلا
2       es   Hola

df['list_of_tuples'] = list(df[['language', 'greeting']].to_records(index=False))
df['list_of_tuples']

0    [en, Hi]
1    [ar, اهلا]
2    [es, Hola]

享受吧!

【讨论】:

以上是关于如何从 Pandas 中的两列形成元组列的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Pandas 中连接包含列表(系列)的两列

如何按对象计算熊猫组列中的不同值?

Pandas:将依赖于第三列的相同数据框的两列相乘

如何在 Python 中创建具有两列作为元组或 Pandas 数据框的单个变量?

如何计算包含一组列中的值和 Pandas 数据框中另一列中的另一个值的行数?

如何使用点绘制熊猫数据框的两列