在dataframe中组合两列文本

w46czmvw  于 2021-08-25  发布在  Java
关注(0)|答案(19)|浏览(314)

我有一个使用pandas的python 20 x 4000 Dataframe 。其中两列被命名为 Yearquarter . 我想创建一个名为 period 那就 Year = 2000quarter= q2 进入 2000q2 .
有人能帮忙吗?

ss2ws0br

ss2ws0br1#

可以使用dataframe的分配方法:

df= (pd.DataFrame({'Year': ['2014', '2015'], 'quarter': ['q1', 'q2']}).
  assign(period=lambda x: x.Year+x.quarter ))
ikfrs5lh

ikfrs5lh2#

def madd(x):
    """Performs element-wise string concatenation with multiple input arrays.

    Args:
        x: iterable of np.array.

    Returns: np.array.
    """
    for i, arr in enumerate(x):
        if type(arr.item(0)) is not str:
            x[i] = x[i].astype(str)
    return reduce(np.core.defchararray.add, x)

例如:

data = list(zip([2000]*4, ['q1', 'q2', 'q3', 'q4']))
df = pd.DataFrame(data=data, columns=['Year', 'quarter'])
df['period'] = madd([df[col].values for col in ['Year', 'quarter']])

df

    Year    quarter period
0   2000    q1  2000q1
1   2000    q2  2000q2
2   2000    q3  2000q3
3   2000    q4  2000q4
hmmo2u0o

hmmo2u0o3#

使用 .combine_first .

df['Period'] = df['Year'].combine_first(df['Quarter'])
wydwbb8l

wydwbb8l4#

下面是我对上述解决方案的总结,使用列值之间的分隔符,将两个具有int和str值的列连接/组合到一个新列中。为此,有三种解决方案。


# be cautious about the separator, some symbols may cause "SyntaxError: EOL while scanning string literal".

# e.g. ";;" as separator would raise the SyntaxError

separator = "&&" 

# pd.Series.str.cat() method does not work to concatenate / combine two columns with int value and str value. This would raise "AttributeError: Can only use .cat accessor with a 'category' dtype"

df["period"] = df["Year"].map(str) + separator + df["quarter"]
df["period"] = df[['Year','quarter']].apply(lambda x : '{} && {}'.format(x[0],x[1]), axis=1)
df["period"] = df.apply(lambda x: f'{x["Year"]} && {x["quarter"]}', axis=1)
ruoxqz4g

ruoxqz4g5#

我的看法。。。。

listofcols = ['col1','col2','col3']
df['combined_cols'] = ''

for column in listofcols:
    df['combined_cols'] = df['combined_cols'] + ' ' + df[column]
'''
zaq34kh6

zaq34kh66#

正如前面提到的,您必须将每个列转换为字符串,然后使用加号运算符组合两个字符串列。通过使用numpy,您可以获得很大的性能改进。

%timeit df['Year'].values.astype(str) + df.quarter
71.1 ms ± 3.76 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

%timeit df['Year'].astype(str) + df['quarter']
565 ms ± 22.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
a5g8bdjr

a5g8bdjr7#

如果两列都是字符串,则可以直接连接它们:

df["period"] = df["Year"] + df["quarter"]

如果其中一列(或两列)不是字符串类型,则应首先转换该列,

df["period"] = df["Year"].astype(str) + df["quarter"]

做这件事时要当心南斯!

如果需要连接多个字符串列,可以使用 agg :

df['period'] = df[['Year', 'quarter', ...]].agg('-'.join, axis=1)

其中“-”是分隔符。

mbzjlibv

mbzjlibv8#

小型数据集(<150行)

[''.join(i) for i in zip(df["Year"].map(str),df["quarter"])]

或稍慢但更紧凑:

df.Year.str.cat(df.quarter)

较大的数据集(>150行)

df['Year'].astype(str) + df['quarter']

更新:时序图0.23.4

让我们在200k行df上测试它:

In [250]: df
Out[250]:
   Year quarter
0  2014      q1
1  2015      q2

In [251]: df = pd.concat([df] * 10**5)

In [252]: df.shape
Out[252]: (200000, 2)

更新:使用pandas 0.19.0的新计时
没有cpu/gpu优化的计时(从最快到最慢排序):

In [107]: %timeit df['Year'].astype(str) + df['quarter']
10 loops, best of 3: 131 ms per loop

In [106]: %timeit df['Year'].map(str) + df['quarter']
10 loops, best of 3: 161 ms per loop

In [108]: %timeit df.Year.str.cat(df.quarter)
10 loops, best of 3: 189 ms per loop

In [109]: %timeit df.loc[:, ['Year','quarter']].astype(str).sum(axis=1)
1 loop, best of 3: 567 ms per loop

In [110]: %timeit df[['Year','quarter']].astype(str).sum(axis=1)
1 loop, best of 3: 584 ms per loop

In [111]: %timeit df[['Year','quarter']].apply(lambda x : '{}{}'.format(x[0],x[1]), axis=1)
1 loop, best of 3: 24.7 s per loop

使用cpu/gpu优化的计时:

In [113]: %timeit df['Year'].astype(str) + df['quarter']
10 loops, best of 3: 53.3 ms per loop

In [114]: %timeit df['Year'].map(str) + df['quarter']
10 loops, best of 3: 65.5 ms per loop

In [115]: %timeit df.Year.str.cat(df.quarter)
10 loops, best of 3: 79.9 ms per loop

In [116]: %timeit df.loc[:, ['Year','quarter']].astype(str).sum(axis=1)
1 loop, best of 3: 230 ms per loop

In [117]: %timeit df[['Year','quarter']].astype(str).sum(axis=1)
1 loop, best of 3: 230 ms per loop

In [118]: %timeit df[['Year','quarter']].apply(lambda x : '{}{}'.format(x[0],x[1]), axis=1)
1 loop, best of 3: 9.38 s per loop

回答@anton vbr的贡献

kmpatx3s

kmpatx3s9#

df = pd.DataFrame({'Year': ['2014', '2015'], 'quarter': ['q1', 'q2']})
df['period'] = df[['Year', 'quarter']].apply(lambda x: ''.join(x), axis=1)

生成此 Dataframe

Year quarter  period
0  2014      q1  2014q1
1  2015      q2  2015q2

此方法通过替换 df[['Year', 'quarter']] 使用 Dataframe 的任何列切片,例如。 df.iloc[:,0:2].apply(lambda x: ''.join(x), axis=1) .
您可以在此处查看有关apply()方法的更多信息

vof42yt1

vof42yt110#

方法 cat().str accessor在这方面非常有效:

>>> import pandas as pd
>>> df = pd.DataFrame([["2014", "q1"], 
...                    ["2015", "q3"]],
...                   columns=('Year', 'Quarter'))
>>> print(df)
   Year Quarter
0  2014      q1
1  2015      q3
>>> df['Period'] = df.Year.str.cat(df.Quarter)
>>> print(df)
   Year Quarter  Period
0  2014      q1  2014q1
1  2015      q3  2015q3
``` `cat()` 甚至允许您添加分隔符,例如,假设您只有年份和期间的整数,您可以这样做:

import pandas as pd
df = pd.DataFrame([[2014, 1],
... [2015, 3]],
... columns=('Year', 'Quarter'))
print(df)
Year Quarter
0 2014 1
1 2015 3
df['Period'] = df.Year.astype(str).str.cat(df.Quarter.astype(str), sep='q')
print(df)
Year Quarter Period
0 2014 1 2014q1
1 2015 3 2015q3

连接多个列只是将序列列表或包含除第一列以外的所有列的 Dataframe 作为参数传递给 `str.cat()` 在第一列(系列)上调用:

df = pd.DataFrame(
... [['USA', 'Nevada', 'Las Vegas'],
... ['Brazil', 'Pernambuco', 'Recife']],
... columns=['Country', 'State', 'City'],
... )
df['AllTogether'] = df['Country'].str.cat(df'State', 'City', sep=' - ')
print(df)
Country State City AllTogether
0 USA Nevada Las Vegas USA - Nevada - Las Vegas
1 Brazil Pernambuco Recife Brazil - Pernambuco - Recife

请注意,如果pandas dataframe/series具有空值,则需要包含参数na_rep以用字符串替换nan值,否则组合列将默认为nan。
6tr1vspr

6tr1vspr11#

这次将lamba函数与string.format()一起使用。

import pandas as pd
df = pd.DataFrame({'Year': ['2014', '2015'], 'Quarter': ['q1', 'q2']})
print df
df['YearQuarter'] = df[['Year','Quarter']].apply(lambda x : '{}{}'.format(x[0],x[1]), axis=1)
print df

  Quarter  Year
0      q1  2014
1      q2  2015
  Quarter  Year YearQuarter
0      q1  2014      2014q1
1      q2  2015      2015q2

这允许您使用非字符串并根据需要重新格式化值。

import pandas as pd
df = pd.DataFrame({'Year': ['2014', '2015'], 'Quarter': [1, 2]})
print df.dtypes
print df

df['YearQuarter'] = df[['Year','Quarter']].apply(lambda x : '{}q{}'.format(x[0],x[1]), axis=1)
print df

Quarter     int64
Year       object
dtype: object
   Quarter  Year
0        1  2014
1        2  2015
   Quarter  Year YearQuarter
0        1  2014      2014q1
1        2  2015      2015q2
2hh7jdfx

2hh7jdfx12#

概括到多个列,为什么不:

columns = ['whatever', 'columns', 'you', 'choose']
df['period'] = df[columns].astype(str).sum(axis=1)
qacovj5a

qacovj5a13#

尽管@silvado的答案是好的,如果你改变 df.map(str)df.astype(str) 它将更快:

import pandas as pd
df = pd.DataFrame({'Year': ['2014', '2015'], 'quarter': ['q1', 'q2']})

In [131]: %timeit df["Year"].map(str)
10000 loops, best of 3: 132 us per loop

In [132]: %timeit df["Year"].astype(str)
10000 loops, best of 3: 82.2 us per loop
weylhg0b

weylhg0b14#

让我们假设你的 dataframedf 带柱 YearQuarter .

import pandas as pd
df = pd.DataFrame({'Quarter':'q1 q2 q3 q4'.split(), 'Year':'2000'})

假设我们想要看到 Dataframe ;

df
>>>  Quarter    Year
   0    q1      2000
   1    q2      2000
   2    q3      2000
   3    q4      2000

最后,连接 YearQuarter 具体如下。

df['Period'] = df['Year'] + ' ' + df['Quarter']

你现在可以
print df 查看生成的 Dataframe 。

df
>>>  Quarter    Year    Period
    0   q1      2000    2000 q1
    1   q2      2000    2000 q2
    2   q3      2000    2000 q3
    3   q4      2000    2000 q4

如果你不想要年和季度之间的空间,只需通过这样做来移除它;

df['Period'] = df['Year'] + df['Quarter']
yi0zb3m4

yi0zb3m415#

以下是一个我认为非常通用的实现:

In [1]: import pandas as pd 

In [2]: df = pd.DataFrame([[0, 'the', 'quick', 'brown'],
   ...:                    [1, 'fox', 'jumps', 'over'], 
   ...:                    [2, 'the', 'lazy', 'dog']],
   ...:                   columns=['c0', 'c1', 'c2', 'c3'])

In [3]: def str_join(df, sep, *cols):
   ...:     from functools import reduce
   ...:     return reduce(lambda x, y: x.astype(str).str.cat(y.astype(str), sep=sep), 
   ...:                   [df[col] for col in cols])
   ...: 

In [4]: df['cat'] = str_join(df, '-', 'c0', 'c1', 'c2', 'c3')

In [5]: df
Out[5]: 
   c0   c1     c2     c3                cat
0   0  the  quick  brown  0-the-quick-brown
1   1  fox  jumps   over   1-fox-jumps-over
2   2  the   lazy    dog     2-the-lazy-dog

相关问题