Saya memiliki 20 x 4000 dataframe di Python menggunakan panda. Dua kolom ini diberi nama Year
dan quarter
. Saya ingin membuat variabel bernama period
make Year = 2000
and quarter= q2
into 2000q2
.
Adakah yang bisa membantu dengan itu?
Saya memiliki 20 x 4000 dataframe di Python menggunakan panda. Dua kolom ini diberi nama Year
dan quarter
. Saya ingin membuat variabel bernama period
make Year = 2000
and quarter= q2
into 2000q2
.
Adakah yang bisa membantu dengan itu?
Jawaban:
jika kedua kolom adalah string, Anda dapat menggabungkannya secara langsung:
df["period"] = df["Year"] + df["quarter"]
Jika salah satu (atau keduanya) dari kolom tidak diketik string, Anda harus mengubahnya terlebih dahulu,
df["period"] = df["Year"].astype(str) + df["quarter"]
Jika Anda harus bergabung dengan beberapa kolom string, Anda dapat menggunakan agg
:
df['period'] = df[['Year', 'quarter', ...]].agg('-'.join, axis=1)
Di mana "-" adalah pemisah.
sum
.
dataframe["period"] = dataframe["Year"].map(str) + dataframe["quarter"].map(str)
peta hanya menerapkan konversi string ke semua entri.
df = pd.DataFrame({'Year': ['2014', '2015'], 'quarter': ['q1', 'q2']})
df['period'] = df[['Year', 'quarter']].apply(lambda x: ''.join(x), axis=1)
Menghasilkan kerangka data ini
Year quarter period
0 2014 q1 2014q1
1 2015 q2 2015q2
Metode ini menggeneralisasi ke jumlah kolom string yang sewenang-wenang dengan mengganti df[['Year', 'quarter']]
dengan setiap potongan kolom dari kerangka data Anda, misalnyadf.iloc[:,0:2].apply(lambda x: ''.join(x), axis=1)
.
Anda dapat memeriksa informasi lebih lanjut tentang metode apply () di sini
lambda x: ''.join(x)
hanya saja ''.join
, bukan?
lambda x: ''.join(x)
konstruksi tidak melakukan apa-apa; itu seperti menggunakan lambda x: sum(x)
bukan hanya sum
.
''.join
, yaitu: df['period'] = df[['Year', 'quarter']].apply(''.join, axis=1)
.
join
hanya mengambil str
contoh dalam iterable. Gunakan map
untuk mengonversikan semuanya menjadi str
dan kemudian gunakan join
.
[''.join(i) for i in zip(df["Year"].map(str),df["quarter"])]
atau sedikit lebih lambat tetapi lebih kompak:
df.Year.str.cat(df.quarter)
df['Year'].astype(str) + df['quarter']
UPDATE: Grafik waktu Pandas 0.23.4
Mari kita uji pada 200K baris 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)
MEMPERBARUI: timing baru menggunakan Pandas 0.19.0
Pengaturan waktu tanpa pengoptimalan CPU / GPU (diurutkan dari yang tercepat ke yang paling lambat):
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
Pengaturan waktu menggunakan pengoptimalan 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
Jawab kontribusi oleh @ anton-vbr
df.T.apply(lambda x: x.str.cat(sep=''))
Metode cat()
dari .str
accessor bekerja dengan sangat baik untuk ini:
>>> 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()
bahkan memungkinkan Anda untuk menambahkan pemisah jadi, misalnya, misalkan Anda hanya memiliki bilangan bulat untuk tahun dan periode, Anda dapat melakukan ini:
>>> 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
Bergabung dengan banyak kolom hanyalah masalah meneruskan daftar seri atau bingkai data yang berisi semua kecuali kolom pertama sebagai parameter untuk str.cat()
dipanggil pada kolom pertama (Seri):
>>> 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
Perhatikan bahwa jika bingkai / seri data panda Anda memiliki nilai nol, Anda harus menyertakan parameter na_rep untuk mengganti nilai NaN dengan string, jika tidak, kolom gabungan akan default ke NaN.
lambda
atau map
; juga hanya terbaca paling bersih.
str.cat()
. Saya akan mengubah jawabannya
sep
kata kunci? dalam panda-0.23.4. Terima kasih!
sep
parameter hanya diperlukan jika Anda berniat untuk memisahkan bagian-bagian dari string bersambung. Jika Anda mendapatkan kesalahan, tolong tunjukkan kepada kami contoh Anda yang gagal.
Penggunaan fungsi lamba kali ini dengan 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
Ini memungkinkan Anda untuk bekerja dengan nilai-nilai non-string dan memformat ulang sesuai kebutuhan.
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
Jawaban sederhana untuk pertanyaan Anda.
year quarter
0 2000 q1
1 2000 q2
> df['year_quarter'] = df['year'] + '' + df['quarter']
> print(df['year_quarter'])
2000q1
2000q2
Year
bukan string
df['Year'].astype(str) + '' + df['quarter'].astype(str)
Meskipun jawaban @silvado baik jika Anda mengubah df.map(str)
untuk df.astype(str)
itu akan lebih cepat:
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
Mari kita misalkan Anda dataframe
yaitu df
dengan kolom Year
dan Quarter
.
import pandas as pd
df = pd.DataFrame({'Quarter':'q1 q2 q3 q4'.split(), 'Year':'2000'})
Misalkan kita ingin melihat kerangka data;
df
>>> Quarter Year
0 q1 2000
1 q2 2000
2 q3 2000
3 q4 2000
Akhirnya, gabungkan Year
dan Quarter
sebagai berikut.
df['Period'] = df['Year'] + ' ' + df['Quarter']
Anda sekarang print
df
dapat melihat kerangka data yang dihasilkan.
df
>>> Quarter Year Period
0 q1 2000 2000 q1
1 q2 2000 2000 q2
2 q3 2000 2000 q3
3 q4 2000 2000 q4
Jika Anda tidak ingin ruang antara tahun dan kuartal, cukup hapus dengan melakukan;
df['Period'] = df['Year'] + df['Quarter']
df['Period'] = df['Year'].map(str) + df['Quarter'].map(str)
TypeError: Series cannot perform the operation +
ketika saya menjalankan salah satu df2['filename'] = df2['job_number'] + '.' + df2['task_number']
atau df2['filename'] = df2['job_number'].map(str) + '.' + df2['task_number'].map(str)
.
df2['filename'] = df2['job_number'].astype(str) + '.' + df2['task_number'].astype(str)
berhasil.
dataframe
yang saya buat di atas, Anda akan melihat bahwa semua kolom adalah string
s.
Berikut ini adalah implementasi yang menurut saya sangat serbaguna:
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
Saat data Anda dimasukkan ke dalam kerangka data, perintah ini akan menyelesaikan masalah Anda:
df['period'] = df[['Year', 'quarter']].apply(lambda x: ' '.join(x.astype(str)), axis=1)
lebih efisien
def concat_df_str1(df):
""" run time: 1.3416s """
return pd.Series([''.join(row.astype(str)) for row in df.values], index=df.index)
dan ini adalah tes waktu:
import numpy as np
import pandas as pd
from time import time
def concat_df_str1(df):
""" run time: 1.3416s """
return pd.Series([''.join(row.astype(str)) for row in df.values], index=df.index)
def concat_df_str2(df):
""" run time: 5.2758s """
return df.astype(str).sum(axis=1)
def concat_df_str3(df):
""" run time: 5.0076s """
df = df.astype(str)
return df[0] + df[1] + df[2] + df[3] + df[4] + \
df[5] + df[6] + df[7] + df[8] + df[9]
def concat_df_str4(df):
""" run time: 7.8624s """
return df.astype(str).apply(lambda x: ''.join(x), axis=1)
def main():
df = pd.DataFrame(np.zeros(1000000).reshape(100000, 10))
df = df.astype(int)
time1 = time()
df_en = concat_df_str4(df)
print('run time: %.4fs' % (time() - time1))
print(df_en.head(10))
if __name__ == '__main__':
main()
final, ketika sum
(concat_df_str2) digunakan, hasilnya tidak hanya concat, itu akan ditransformasikan ke integer.
df.values[:, 0:3]
atau df.values[:, [0,2]]
.
generalisasi ke beberapa kolom, mengapa tidak:
columns = ['whatever', 'columns', 'you', 'choose']
df['period'] = df[columns].astype(str).sum(axis=1)
Menggunakan zip
bisa lebih cepat:
df["period"] = [''.join(i) for i in zip(df["Year"].map(str),df["quarter"])]
Grafik:
import pandas as pd
import numpy as np
import timeit
import matplotlib.pyplot as plt
from collections import defaultdict
df = pd.DataFrame({'Year': ['2014', '2015'], 'quarter': ['q1', 'q2']})
myfuncs = {
"df['Year'].astype(str) + df['quarter']":
lambda: df['Year'].astype(str) + df['quarter'],
"df['Year'].map(str) + df['quarter']":
lambda: df['Year'].map(str) + df['quarter'],
"df.Year.str.cat(df.quarter)":
lambda: df.Year.str.cat(df.quarter),
"df.loc[:, ['Year','quarter']].astype(str).sum(axis=1)":
lambda: df.loc[:, ['Year','quarter']].astype(str).sum(axis=1),
"df[['Year','quarter']].astype(str).sum(axis=1)":
lambda: df[['Year','quarter']].astype(str).sum(axis=1),
"df[['Year','quarter']].apply(lambda x : '{}{}'.format(x[0],x[1]), axis=1)":
lambda: df[['Year','quarter']].apply(lambda x : '{}{}'.format(x[0],x[1]), axis=1),
"[''.join(i) for i in zip(dataframe['Year'].map(str),dataframe['quarter'])]":
lambda: [''.join(i) for i in zip(df["Year"].map(str),df["quarter"])]
}
d = defaultdict(dict)
step = 10
cont = True
while cont:
lendf = len(df); print(lendf)
for k,v in myfuncs.items():
iters = 1
t = 0
while t < 0.2:
ts = timeit.repeat(v, number=iters, repeat=3)
t = min(ts)
iters *= 10
d[k][lendf] = t/iters
if t > 2: cont = False
df = pd.concat([df]*step)
pd.DataFrame(d).plot().legend(loc='upper center', bbox_to_anchor=(0.5, -0.15))
plt.yscale('log'); plt.xscale('log'); plt.ylabel('seconds'); plt.xlabel('df rows')
plt.show()
Solusi paling sederhana:
Solusi Umum
df['combined_col'] = df[['col1', 'col2']].astype(str).apply('-'.join, axis=1)
Solusi khusus pertanyaan
df['quarter_year'] = df[['quarter', 'year']].astype(str).apply(''.join, axis=1)
Tentukan pembatas yang disukai di dalam tanda kutip sebelum .join
Solusi ini menggunakan langkah menengah mengompresi dua kolom DataFrame ke satu kolom yang berisi daftar nilai. Ini berfungsi tidak hanya untuk string tetapi untuk semua jenis kolom-dtypes
import pandas as pd
df = pd.DataFrame({'Year': ['2014', '2015'], 'quarter': ['q1', 'q2']})
df['list']=df[['Year','quarter']].values.tolist()
df['period']=df['list'].apply(''.join)
print(df)
Hasil:
Year quarter list period
0 2014 q1 [2014, q1] 2014q1
1 2015 q2 [2015, q2] 2015q2
Seperti banyak yang telah disebutkan sebelumnya, Anda harus mengubah setiap kolom menjadi string dan kemudian menggunakan operator plus untuk menggabungkan dua kolom string. Anda bisa mendapatkan peningkatan kinerja besar dengan menggunakan 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)
df2['filename'] = df2['job_number'].values.astype(str) + '.' + df2['task_number'].values.astype(str)
-> Keluaran : TypeError: ufunc 'add' did not contain a loop with signature matching types dtype('<U21') dtype('<U21') dtype('<U21')
. Baik job_number dan task_number adalah int.
df['Year'].values.astype(str) + df.quarter
Saya pikir cara terbaik untuk menggabungkan kolom dalam panda adalah dengan mengubah kedua kolom menjadi integer dan kemudian ke str.
df[['Year', 'quarter']] = df[['Year', 'quarter']].astype(int).astype(str)
df['Period']= df['Year'] + 'q' + df['quarter']
Berikut ini adalah ringkasan saya dari solusi di atas untuk menggabungkan / menggabungkan dua kolom dengan nilai int dan str ke dalam kolom baru, menggunakan pemisah antara nilai kolom. Tiga solusi berfungsi untuk tujuan ini.
# 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)
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)
Sebagai contoh:
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
dataframe["period"] = dataframe["Year"].astype(str).add(dataframe["quarter"])
atau jika nilainya seperti [2000] [4] dan ingin membuat [2000q4]
dataframe["period"] = dataframe["Year"].astype(str).add('q').add(dataframe["quarter"]).astype(str)
menggantikan .astype(str)
dengan .map(str)
karya juga.
add(dataframe.iloc[:, 0:10])
misalnya?