在pandas / python中结合数据框中的两列文本
我有一个使用pandaspython 20 x 4000数据框。 其中两列被命名为年份和季度。 我想创build一个名为period的variables,使Year = 2000和Quarter = q2成为2000q2
任何人都可以帮忙吗?
dataframe["period"] = dataframe["Year"].map(str) + dataframe["quarter"]
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']]
replace为数据df.iloc[:,0:2].apply(lambda x: ''.join(x), axis=1)
任意列片段,例如df.iloc[:,0:2].apply(lambda x: ''.join(x), axis=1)
。
还有另一种方法来做到这一点:
df['period'] = df['Year'].astype(str) + df['quarter']
或者慢一点:
df['period'] = df[['Year','quarter']].astype(str).sum(axis=1)
我们来testing一下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)
更新:使用pandas0.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
.str
访问器的方法cat()
可以很好地工作:
>>> 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
这次使用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
这使您可以根据需要使用非string和重新格式化值。
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
虽然@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
这是一个我觉得非常灵活的实现:
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
当你的数据被插入数据框时,这个命令应该可以解决你的问题:
df['period'] = df[['Year', 'quarter']].apply(lambda x: ' '.join(x.astype(str)), axis=1)
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
正如前面提到的,必须将每列转换为string,然后使用加号运算符来组合两个string列。 你可以通过使用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)